Чтобы в полной мере использовать возможности сценариев оболочки (и программирования), необходимо владеть регулярными выражениями. Некоторые команды и утилиты, обычно используемые в скриптах, например grep, expr, sed и awk, используют RE.

В этой статье мы поговорим о регулярных выражениях. Ниже приводится «Оглавление», чтобы вы могли понять суть того, что будет рассмотрено, и помочь в навигации:

· Что такое регулярное выражение?
· Метасимволы регулярного выражения
· Как работает механизм регулярных выражений?
· Наборы символов (или классы): []
· Наборы слов (чередование): |
· Точка
· Якоря
· Повторение (?, *, +)
· Группировка и Обратные ссылки
∘ _ Обратные ссылки
∘ _ Именованные группы захвата
∘ _ Группы сброса ветвей
· Режимы сопоставления регулярных выражений
· Модификаторы режима
· Атомарная группировка и остальные темы
· Производительность регулярных выражений
· Использование регулярных выражений в оболочке Linux
· Ссылки

Что такое регулярное выражение?

Регулярные выражения - это наборы символов и / или метасимволов, которые соответствуют (или задают) шаблоны. Основное использование регулярных выражений (RE) - это текстовый поиск и манипуляции со строками. RE соответствует одиночному символу или набору символов - строке или части строки.

Символы, интерпретация которых выходит за рамки их буквального значения, называются метасимволами.

Шаблон регулярного выражения

Обычно вы определяете шаблон Regex, заключая этот шаблон (без дополнительных кавычек) в две косые черты. Например, /\w/ и /[aeiou]/.

Чувствительность к регистру:

Обратите внимание, что обработчики регулярных выражений по умолчанию чувствительны к регистру, если вы не укажете механизму регулярных выражений игнорировать различия в регистре.

Regex использует:

Когда вы просматриваете строку (может быть многострочную) с шаблоном регулярного выражения, вы можете получить следующую информацию:

  • Есть ли совпадение или нет
  • Соответствующие подстроки в заданной строке
  • Положение этой подстроки в заданной строке
  • Группировать обратные ссылки для каждой подстроки
  • При использовании с \A и \Z, а не с совпадающей подстрокой, мы можем сопоставить всю данную строку как единое целое.

Метасимволы регулярных выражений

Внутри шаблона все символы, кроме (, ), [, ], {, }, |, \, ?, *, +, ., ^ и $ соответствуют сами себе. Если вы хотите буквально сопоставить один из специальных символов в шаблоне, поставьте перед ним обратную косую черту.

Примечание. Даже / нельзя использовать внутри шаблона, его можно избежать, поставив перед ним обратную косую черту.

Большинство разновидностей регулярных выражений рассматривают скобку { как буквальный символ, если только она не является частью оператора повторения, такого как {1,3}. Таким образом, вам обычно не нужно экранировать его с помощью обратной косой черты, хотя вы можете это сделать, если хотите. Исключением из этого правила является java.util.regex package, который требует экранирования всех буквальных скобок.

Экранирование метасимвола:

\ (обратная косая черта) используется для экранирования специальных символов и используется для придания особого значения некоторым нормальным символам. Например, \1 используется для обратной ссылки на первое слово, а \d означает цифровой символ, а \D означает нецифровой символ, а также для указания непечатаемых символов, таких как \n (LF), \r (CR) и \t (табуляция). .

Примечание. Обратную косую черту также можно избежать с помощью обратной косой черты.

Экранирование одного метасимвола с помощью обратной косой черты работает во всех разновидностях регулярных выражений.

Все остальные символы не должны экранироваться обратной косой чертой. Это потому, что обратная косая черта также является специальным символом. Обратная косая черта в сочетании с буквальным символом может создать токен регулярного выражения со специальным значением. Например, \d будет соответствовать одной цифре от 0 до 9.

Как программист, вы можете быть удивлены тем, что такие символы, как одинарная кавычка и двойная кавычка, не являются специальными символами.

Специальные символы и языки программирования:

В исходном коде вы должны помнить, какие символы внутри строк обрабатываются вашим языком программирования в особом порядке. Это потому, что эти символы будут обработаны компилятором до того, как библиотека регулярных выражений увидит строку.

Непечатаемые символы:

Вы можете использовать специальные последовательности символов, чтобы поместить непечатаемые символы в регулярное выражение.

  • Используйте \t для соответствия символу табуляции (ASCII 0x09), \r для возврата каретки (0x0D) и \n для перевода строки (0x0A).
  • Более экзотические непечатаемые формы - это \a (звонок, 0x07), \e (escape, 0x1B), \f (подача формы, 0x0C) и \v (вертикальная табуляция, 0x0B).
  • Помните, что текстовые файлы Windows используют \r\n для завершения строк, а текстовые файлы UNIX (Linux и Mac OS X) используют \n (LF) и \r (CR) в более старых версиях Mac OS.
  • Вы можете включить любой символ в свое регулярное выражение, если вы знаете его шестнадцатеричный код ASCII или ANSI для набора символов, с которым вы работаете. В наборе символов Latin-1 символом авторского права является символ 0xA9. Итак, для поиска символа авторского права вы можете использовать \xA9.
  • Если ваш обработчик регулярных выражений поддерживает Юникод, используйте \uFFFF вместо \xFF для вставки символа Юникода. Знак валюты евро занимает кодовую точку 0x20AC. Если вы не можете ввести его на клавиатуре, вы можете вставить его в регулярное выражение с помощью \u20AC.

Базовые и расширенные регулярные выражения:

См .: http://www.gnu.org/software/grep/manual/html_node/Basic-vs-Extended.html

В основных регулярных выражениях метасимволы ?, +, {, |, ( и ) теряют свое особое значение; вместо этого используйте версии с обратной косой чертой \?, \+, \{, \|, \( и \).

Переносимые скрипты должны избегать шаблонов { is grep -E и должны использовать [{] для соответствия литералу {. Некоторые реализации поддерживают \{ как метасимвол.

Как Regex Engine работает внутри?

Знание того, как работает механизм регулярных выражений, позволит вам легче создавать лучшие регулярные выражения.

Механизмы, ориентированные на регулярные выражения, более мощные:

Существует два типа обработчиков регулярных выражений:

  • ориентированные на текст движки и
  • управляемые регулярным выражением (важные) движки.

Некоторые очень полезные функции, такие как ленивые квантификаторы и обратные ссылки, могут быть реализованы только в механизмах, ориентированных на регулярные выражения. Неудивительно, что такие движки более популярны.

Известными инструментами, использующими движки, ориентированные на текст, являются awk, egrep, flex, lex, MySQL и Procmail. Для awk и egrep существует несколько версий этих инструментов, в которых используется механизм, управляемый регулярными выражениями.

Вы можете легко узнать, имеет ли вариант регулярного выражения, который вы собираетесь использовать, движок, ориентированный на текст или на регулярное выражение. Если доступны обратные ссылки и / или ленивые квантификаторы, вы можете быть уверены, что движок ориентирован на регулярные выражения. Вы можете выполнить тест, применив регулярное выражение /regex|regex not/ к строке regex not. Если результирующим совпадением является только регулярное выражение, движок ориентирован на регулярное выражение. Если результат не является регулярным выражением, он ориентирован на текст. Причина в том, что движок, управляемый регулярными выражениями, очень хочет.

Механизм, ориентированный на регулярные выражения, всегда возвращает самое левое совпадение:

Это очень важный момент для понимания: движок, ориентированный на регулярное выражение, всегда будет возвращать самое левое совпадение, даже если «лучшее» совпадение может быть найдено позже. При применении регулярного выражения к строке движок запускается с первого символа строки. Он будет пробовать все возможные перестановки регулярного выражения для первого символа. Только в том случае, если все возможности были опробованы и оказались безуспешными, машина продолжит работу со вторым символом в тексте. Опять же, он будет пробовать все возможные перестановки регулярного выражения в том же порядке. В результате движок, ориентированный на регулярное выражение, вернет самое левое совпадение.

Наборы символов (или классы): [ ]

С помощью «набора символов» вы можете указать механизму регулярных выражений соответствовать только «одному» из нескольких символов (порядок, в котором символы перечислены в наборе символов, не имеет значения). Просто поместите символы, которые вы хотите сопоставить, между квадратными скобками ([ и ]). Если вы хотите сопоставить a или e, используйте [ae]. Вы можете использовать это в gr[ae]y для соответствия "серому" или "серому".

Класс символов соответствует только одному символу. gr[ae]y не будет соответствовать "graay", "greey" или тому подобному. Порядок символов внутри класса символов не имеет значения. Результаты идентичны.

Диапазоны:

Вы можете использовать дефис (-) внутри класса символов, чтобы указать диапазон символов. [0-9] соответствует одной цифре от 0 до 9. Вы можете использовать более одного диапазона. [0-9a-fA-F] соответствует одной шестнадцатеричной цифре без учета регистра. Вы можете комбинировать диапазоны и отдельные символы. [0-9a-fxA-FX] соответствует шестнадцатеричной цифре или букве X. Вы можете иметь несколько диапазонов в наборе символов (чтобы выбрать только символ из всех этих диапазонов). Опять же, порядок символов и диапазонов не имеет значения.

Отрицательные классы символов:

Если ввести каретку (^) после открывающей квадратной скобки, набор символов будет отменен. В результате набор символов будет соответствовать любому символу, которого нет в наборе символов. В отличие от точки, инвертированные классы символов также соответствуют пробелам и (невидимым) символам разрыва строки.

Обратите внимание, что символ вставки после открывающей квадратной скобки отрицает «весь набор символов», а не только символ сразу после него.

Важно помнить, что отрицаемый класс символов по-прежнему должен соответствовать символу. q[^ut] не означает: «q, за которым не следует u или t». Это означает: «q, за которым следует символ, не являющийся u или t». Он не будет соответствовать q в строке «Ирак». Он будет соответствовать q и пробелу после q в «Ирак - страна». В самом деле: пробел будет частью общего совпадения, потому что это «символ, который не является u или t», которому соответствует инвертированный класс символов в приведенном выше регулярном выражении.

Метасимволы внутри наборов символов:

Обратите внимание, что единственными специальными символами или метасимволами внутри класса символов являются закрывающая скобка (]), обратная косая черта (\), каретка (^ ) и дефис (-). Обычные метасимволы - это обычные символы внутри класса символов, и их не нужно экранировать обратной косой чертой. Для поиска звездочки или плюса используйте [+*].

Регулярное выражение будет работать нормально, если вы избегаете обычных метасимволов внутри класса символов, но это значительно снижает удобочитаемость.

Чтобы включить обратную косую черту как символ без какого-либо специального значения внутри класса символов, вы должны экранировать его с помощью другой обратной косой черты. [\\x] соответствует обратной косой черте или x.

Закрывающую скобку (]), каретку (^) и дефис (-) можно добавить, экранировав их обратной косой чертой или поместив их в положение, в котором они не имеют особого значения . Рекомендуется использовать второй метод, так как он улучшает читаемость.

  • Чтобы вставить курсор, поместите его в любом месте, кроме открывающей скобки. [x^] соответствует x или символу вставки.
  • Вы можете поместить закрывающую скобку сразу после открывающей скобки или отрицательной вставки. []x] соответствует закрывающей скобке или x. [^]x] соответствует любому символу, кроме закрывающей скобки или x.
  • Дефис может быть включен сразу после открывающей скобки, или прямо перед закрывающей скобкой, или сразу после отрицательной вставки. И [-x], и [x-] соответствуют x или дефису.

Вы можете использовать все непечатаемые символы в классах символов так же, как вы можете использовать их вне классов символов. Например. [$\u20AC] соответствует знаку доллара или евро, если ваше регулярное выражение поддерживает Unicode.

Регулярное выражение POSIX:

Регулярные выражения POSIX обрабатывают обратную косую черту как буквальный символ внутри классов символов. Это означает, что вы не можете использовать обратную косую черту для экранирования закрывающей скобки (]), символа вставки (^) и дефиса (-). Чтобы использовать эти символы, расположите их, как описано выше в этом разделе. Это также означает, что специальные токены, такие как сокращения, недоступны в регулярных выражениях POSIX.

Сокращенные классы символов:

Поскольку определенные классы символов используются часто, доступен ряд сокращенных классов символов:

  • \d - это сокращение от [0-9].
  • \w означает словесный символ, обычно [A-Za-z0-9_]. Обратите внимание на наличие символа подчеркивания и цифр.
  • \s означает пробельный символ. Опять-таки, какие символы сюда входят, зависит от вкуса регулярного выражения. В общем, включает [ \t\r\n]. То есть: \s будет соответствовать пробелу, табуляции или разрыву строки. Некоторые варианты включают дополнительные, редко используемые непечатаемые символы, такие как вертикальная табуляция и подача страницы.

Сокращенные классы символов могут использоваться как внутри, так и вне квадратных скобок. Например, \s\d соответствует пробельному символу, за которым следует цифра, а [\s\d] соответствует одиночному символу, который является либо пробелом, либо цифрой.

Отрицательные классы сокращенных символов:

У трех вышеуказанных сокращений также есть инвертированные версии.

  • \D совпадает с [^\d],
  • \W - это сокращение от [^\w] и
  • \S эквивалентно [^\s].

Вычитание класса символов:

Вычитание класса символов упрощает сопоставление любого отдельного символа, присутствующего в одном списке (класс символов), но не присутствующего в другом списке (вычитаемый класс). Синтаксис для этого:

[class-[subtract]]

Если символ после дефиса (-) является открывающей скобкой, эти варианты интерпретируют дефис как оператор вычитания, а не как оператор диапазона. Вы можете использовать полный синтаксис символьного класса внутри вычитаемого символьного класса.

Например, класс символов [a-z-[aeiuo]] соответствует одной букве, которая не является гласной. Другими словами: соответствует единственной согласной.

Вычитание вложенного класса символов:

Поскольку вы можете использовать полный синтаксис символьного класса внутри вычитаемого символьного класса, вы можете вычесть класс из вычитаемого класса. [0-9-[0-6-[0-3]]] сначала вычитает 0-3 из 0-6, давая [0-9-[4-6]] или [0-37-9], что соответствует любому символу в строке 0123789.

Обратите внимание, что вычитание класса всегда должно быть последним элементом в наборе символов. Например, [0-9-[4-6]a-f] не является допустимым регулярным выражением. Его следует переписать как [0-9a-f-[4-6]].

Отрицание имеет приоритет перед вычитанием:

Класс символов [^1234-[3456]] представляет собой как отрицательную, так и вычитаемую форму. Во всех вариантах, поддерживающих вычитание символьного класса, базовый класс инвертируется перед вычитанием из него. Этот класс следует читать как «(не 1234) минус 3456». Таким образом, этот класс символов соответствует любому символу, кроме цифр 1, 2, 3, 4, 5 и 6.

Пересечение классов символов:

Пересечение классов символов поддерживается Java и Ruby. Это упрощает соответствие любому одиночному символу, который должен присутствовать в двух наборах символов. Синтаксис для этого:

[class&&[intersect]]

Вы можете использовать полный синтаксис символьного класса внутри пересекаемого символьного класса. Если пересекаемому классу не нужна отрицательная вставка, вы можете опустить вложенные квадратные скобки:

[class&&intersect]

Например, класс символов [a-z&&[^aeiuo\]] соответствует одной букве, которая не является гласной. Другими словами: соответствует единственной согласной.

Пересечение нескольких классов:

Вы можете пересекать один и тот же класс более одного раза. [0-9&&0-6&&4-9] то же самое, что [4-6], поскольку это единственные цифры, присутствующие во всех трех частях перекрестка. Вы можете написать то же регулярное выражение, что и [0-9&&[0-6]&&[4-9]], [0-9&&[0-6&&4-9]], [0-9&&[0-6]&&4-9], [0-9&&0-6&&[4-9]] или [0-9&&[0-6&&[4-9]]]. Вложенные квадратные скобки нужны только в том случае, если одна из частей перекрестка не указана.

Пересечение в отрицательных классах:

Класс символов [^1234&&3456] одновременно инвертируется и пересекается. В Java отрицание имеет приоритет над пересечением (аналогично его приоритету над вычитанием). Java читает это регулярное выражение как «(не 1234) и 3456». Таким образом, в Java этот класс совпадает с [56] и соответствует цифрам 5 и 6. В Ruby пересечение имеет приоритет перед отрицанием. Руби читает [^1234&&3456] как «не (1234 и 3456)». Таким образом, в Ruby этот класс совпадает с [^34], который соответствует чему угодно, кроме цифр 3 и 4.

Классы повторяющихся символов:

Если вы повторяете класс символов с помощью операторов ?, * или +, вы будете повторять весь класс символов, а не только соответствующий ему символ.

Например,

Регулярное выражение [0-9]+ может соответствовать как «837», так и «222».

Если вы хотите повторить совпадающий символ, а не класс, вам нужно будет использовать обратные ссылки. ([0-9])\1+ будет соответствовать «222», но не «837».

Наборы слов (чередование): |

См .: http://www.regular-expressions.info/alternation.html

Мы уже обсуждали, как мы можем использовать классы символов для сопоставления одного символа из нескольких возможных символов. Чередование аналогично. Мы можем использовать чередование (с использованием вертикальной черты |) для сопоставления одного регулярного выражения из нескольких возможных регулярных выражений.

Например, если вы хотите найти буквальный текст «кошка» или «собака», разделите оба параметра вертикальной чертой или вертикальной чертой: "cat|dog". Если вам нужны дополнительные параметры, просто разверните список: cat|dog|mouse|fish.

Приоритет чередования операторов:

Оператор чередования имеет самый низкий приоритет из всех операторов регулярных выражений. То есть он сообщает механизму регулярных выражений, что нужно сопоставить либо все, что находится слева от вертикальной полосы, либо все, что соответствует справа от вертикальной полосы. Если вы хотите ограничить диапазон чередования, вам нужно будет использовать круглые скобки для группировки.

Если мы хотим улучшить первый пример, чтобы он соответствовал только целым словам, нам нужно будет использовать \b(cat|dog)\b. Это указывает механизму регулярных выражений найти границу слова, затем либо «кошка», либо «собака», а затем еще одну границу слова. Если бы мы опускали круглые скобки, обработчик регулярных выражений искал бы «границу слова, за которой следует кошка» или «собака», за которой следует граница слова.

Обратите внимание, вы должны быть осторожны с предпочтениями оператора. Например,

# Ruby
"A good thing"   =~ /^[Gg]ood|[Bb]ad|best/       #=> nil
"A bad thing"    =~ /^[Gg]ood|[Bb]ad|best/       #=> 2
"A good thing"   =~ /^([Gg]ood|[Bb]ad)|best/     #=> nil
"good thing"     =~ /^([Gg]ood|[Bb]ad)|best/     #=> 0

Обратите внимание, что здесь мы использовали круглые скобки для переопределения приоритета операторов, но у них есть и другое применение. Скобки можно использовать для запоминания совпадающего текста.

Точка

Точка соответствует (почти) любому символу:

Точка соответствует одному символу, не обращая внимания на то, что это за символ. Единственное исключение - символы новой строки. В большинстве разновидностей регулярных выражений точка по умолчанию не соответствует символу новой строки. Таким образом, по умолчанию точка является сокращением от отрицательного класса символов [^\n] (разновидности регулярных выражений UNIX) или [^\r\n] (разновидности регулярных выражений Windows).

Почти во всех языках программирования и библиотеках регулярных выражений активация однострочного режима не имеет никакого эффекта, кроме как заставить точку совпадать с новой строкой.

В JavaScript нет возможности сделать так, чтобы символы разрыва строки совпадали с точками. В JS вы можете использовать класс символов, например [\s\S], чтобы соответствовать любому символу.

Помните: точка не является метасимволом внутри класса символов, поэтому для соответствия символу . нам не нужно экранировать его обратной косой чертой.

Используйте классы отрицательных символов вместо точки:

Инвертированный класс символов часто более уместен, чем точка. Например,

Предположим, вы хотите найти строку в двойных кавычках. Звучит просто. Между двойными кавычками может быть любое количество любых символов, так что ".*", похоже, отлично справляется с задачей. Точка соответствует любому символу, а звездочка позволяет повторять точку любое количество раз, включая ноль. Если вы протестируете это регулярное выражение, поставив «строку» между двойными кавычками, она будет отлично соответствовать «строке». Теперь давай и проверь это на

Houston, we have a problem with "string one" and "string two". Please respond.

Ой. Регулярное выражение соответствует "string one" and "string two". Определенно не то, что мы планировали. Причина в том, что звезда жадная.

Итак, наше первоначальное определение строки в двойных кавычках было ошибочным. Мы не хотим, чтобы в кавычках использовалось какое-либо количество символов. Нам нужно любое количество символов, которые не являются двойными кавычками или новой строкой между кавычками. Итак, правильное регулярное выражение [^"\r\n\]*.

Якоря

Якоря вообще не соответствуют ни одному символу. Вместо этого они соответствуют позиции до, после или между символами.

Границы линий: ^ и $:

Символ ^ - это привязка «начало строки», а символ $ - привязка «конец строки». Их можно использовать в однострочном или многострочном тексте.

Обратите внимание, что ^ является привязкой только в том случае, если это первый символ шаблона регулярного выражения. Точно так же $ является привязкой только в том случае, если это последний символ шаблона регулярного выражения.

Применение ^a к «abc» соответствует a. ^b вообще не будет соответствовать «abc», потому что b не может быть сопоставлен сразу после начала строки, сопоставленной с ^. Точно так же c$ соответствует c в «abc», а a$ не соответствует вообще.

Соответствие шаблону:

совпадения нулевой длины:

Мы видели, что привязки совпадают в позиции, а не соответствуют символу. Это означает, что когда регулярное выражение состоит только из одного или нескольких якорей, оно может привести к совпадению нулевой длины. В зависимости от ситуации это может быть очень полезно или нежелательно.

Строки, линии и многострочный режим:

Обратите внимание, что данная строка может содержать несколько строк.

Если у вас есть строка, состоящая из нескольких строк, например first line\nsecond line (где \n означает разрыв строки), часто желательно работать со строками, а не со всей строкой.

Почти все движки регулярных выражений имеют возможность расширять значение обоих якорей. ^ может тогда соответствовать в начале строки, а также после каждого разрыва строки. Аналогично, $ по-прежнему будет соответствовать в конце строки, а также перед каждым разрывом строки. В текстовых редакторах, таких как EditPad Pro или GNU Emacs, и инструментах регулярных выражений, таких как PowerGREP, каретка и доллар всегда совпадают в начале и конце каждой строки. Это имеет смысл, потому что эти приложения предназначены для работы с файлами целиком, а не с короткими строками.

В большинстве языков программирования и библиотек, кроме Ruby, вам необходимо явно активировать эту расширенную функциональность. Это традиционно называется многострочным режимом. В Perl вы делаете это, добавляя m после кода регулярного выражения, например: m/^regex$/m.

Границы строки: \A и \Z

\A всегда соответствует только началу строки. Аналогично, \Z всегда соответствует только в конце строки. Эти два токена никогда не совпадают при переносе строки. Это верно даже при включении многострочного режима.

В EditPad Pro и PowerGREP, где каретка и доллар всегда совпадают в начале и конце строк, \A и \Z совпадают только в начале и в конце всего файла.

JavaScript, POSIX и XML не поддерживают \A и \Z. Вы застряли в использовании для этой цели каретки и доллара.

Строки, заканчивающиеся разрывом строки:

Несмотря на то, что \Z и $ совпадают только в конце строки (когда параметр для сопоставления каретки и доллара во встроенных разрывах строк отключен), есть одно исключение: если строка заканчивается разрывом строки, то \Z и $ будут соответствовать в позиции перед этим разрывом строки, а не в самом конце строки.

Границы слов:

Что такое словесный символ?

Во всех вариантах символы [a-zA-Z0-9_] являются символами слова. Им также соответствует класс сокращенных символов \w. Ароматизаторы, показывающие «ascii» в качестве границ слов при сравнении вкусов, распознают только эти символы как символы слова. Ароматизаторы, показывающие «ДА», также распознают буквы и цифры из других языков или весь Юникод как символы слова. Обратите внимание, что Java поддерживает Unicode для \b, но не для \w. Python предлагает флаги для управления символами слов (влияет как на \b, так и \w).

«Словесный символ» - это символ, который может использоваться для образования слов. Все символы, которые не являются «словесными символами», являются «несловесными символами».

Якорь \b:

Метасимвол \b - это якорь, такой же как каретка и знак доллара. Он соответствует позиции, которая называется «границей слова». Это совпадение нулевой длины.

Существуют три различных положения, которые квалифицируются как границы слов:

  • Перед первым символом в строке, если первый символ является символом слова.
  • После последнего символа в строке, если последний символ является символом слова.
  • Между двумя символами в строке, где один является символом слова, а другой не является символом слова.

Проще говоря: \b позволяет выполнять поиск «только по целым словам», используя регулярное выражение в форме \bword\b.

Отрицательная граница слова:

\B - это инвертированная версия \b. \B соответствует каждой позиции, а \b - нет. Фактически \B соответствует любой позиции между двумя символами слова, а также любой позиции между двумя символами, не являющимися словами.

Механизм регулярных выражений готов:

Как мы уже говорили, движок регулярных выражений очень хочет. Он прекратит поиск, как только найдет действительное совпадение. Следствием этого является то, что в определенных ситуациях порядок альтернатив имеет значение.

Предположим, вы хотите использовать регулярное выражение для сопоставления списка имён функций на языке программирования: «Get», «GetValue», «Set» или «SetValue». Очевидное решение - Get|GetValue|Set|SetValue. Давайте посмотрим, как это работает, когда строка - «SetValue». Соответствует «Set» в «SetValue».

Повторение (?, *, +)

Где их можно использовать?

Они работают с непосредственно предшествующим «символом» или непосредственно предшествующим «набором символов, заключенным в круглые скобки».

Там природа:

Рассмотрим следующие случаи:

  • .* не означает, что будет повторяться один и тот же символ. Если вы хотите найти повторяющиеся символы, вам потребуется использовать обратные ссылки.
  • \d+ соответствует строке из одной или нескольких цифр. Например 123, 1, 22422
  • 4+ соответствует 4, 44, 444 и т. Д.

Знак вопроса (?):

Знак вопроса делает предыдущий токен в регулярном выражении необязательным (то есть нулевым или однократным).

Например,

  • colou?r соответствует как «цвет», так и «цвет».
  • Nov(ember)? соответствует "ноя" и "ноябрь".

Звездочка (*):

Звездочка или звездочка указывает механизму попытки сопоставить предыдущий токен ноль или более раз.

Например, <[A-Za-z][A-Za-z0-9]*> соответствует тегу HTML без каких-либо атрибутов. Угловые скобки буквальные. Первый символьный класс соответствует букве. Второй класс символов соответствует букве или цифре. Звезда повторяет второй класс символов. Мы также могли использовать <[A-Za-z0-9]+>. Мы этого не сделали, потому что это регулярное выражение будет соответствовать <1>, который не является допустимым тегом HTML.

Плюс (+):

Плюс указывает механизму попытаться сопоставить предыдущий токен один или несколько раз.

Оператор повторения ({min, max}):

Современные разновидности регулярных выражений имеют дополнительный оператор повторения, который позволяет указать, сколько раз токен может повторяться.

Синтаксис: {min,max}

Здесь min - положительное целое число, указывающее минимальное количество совпадений, а max - целое число, равное или большее min, указывающее максимальное количество совпадений.

Если запятая присутствует, но max опущена, максимальное количество совпадений бесконечно. Итак, {0,} то же самое, что *, а {1,} то же самое, что +.

Отсутствие запятой и max указывает механизму повторять токен ровно min раз.

Например, вы можете использовать \b[1-9][0-9]{3}\b для сопоставления числа от 1000 до 9999. \b[1-9][0-9]{2,4}\b соответствует числу от 100 до 99999. Обратите внимание на использование границ слов.

Их жадность:

Знак вопроса, звезда, плюс и оператор повторения - жадные.

Например, вопросительный знак дает механизму регулярных выражений два варианта выбора: попытаться сопоставить часть, к которой относится вопросительный знак, или не пытаться сопоставить его. Двигатель всегда будет пытаться соответствовать этой части. Только если это приведет к сбою всего регулярного выражения, движок попытается игнорировать часть, к которой относится вопросительный знак.

В результате, если вы примените регулярное выражение Feb 23(rd)? к строке «Сегодня 23 февраля 2003 г.», совпадением всегда будет «23 февраля», а не «23 февраля». Точно так же * всегда соответствует самой длинной строке, которая удовлетворяет регулярному выражению. Например, ^s(.*)s будет «сидеть в Starbucks», но не «сидеть в s».

Делать их ленивыми:

Ленивые кванторы иногда также называют нелицеприятными или неохотными. Это можно сделать, поставив вопросительный знак после «вопросительного знака», «плюса», «звездочки» или «оператора повторения» в регулярном выражении.

Отрицательный прогноз:

См .: http://www.regular-expressions.info/lookaround.html

Есть способ отрицать шаблон регулярного выражения, но он работает не везде.

Группировка и обратные ссылки

Поместив часть регулярного выражения в круглые скобки или круглые скобки, вы можете сгруппировать эту часть регулярного выражения вместе. Это позволяет применять оператор регулярного выражения, например. оператор повторения для всей группы.

Обратите внимание, что для группировки можно использовать только круглые скобки. Квадратные скобки определяют класс символов, а фигурные скобки используются специальным «оператором повторения».

Обратные ссылки

Круглые скобки создают обратную ссылку:

Помимо группировки частей регулярного выражения, круглые скобки также создают обратную ссылку. Обратная ссылка сохраняет часть строки, совпадающую с частью регулярного выражения, в круглых скобках.

Например, регулярное выражение Set(Value)? соответствует «Set» или «SetValue». В первом случае первая обратная ссылка будет пустой, потому что она ничего не соответствует. Во втором случае первая обратная ссылка будет содержать Value.

Если вы не используете обратную ссылку, вы можете оптимизировать это регулярное выражение до Set(?:Value)?. Знак вопроса и двоеточие после открывающей круглой скобки - это специальный синтаксис, который вы можете использовать, чтобы сообщить механизму регулярных выражений, что эта пара скобок не должна создавать обратную ссылку. Обратите внимание, что вопросительный знак после открывающей скобки не связан с вопросительным знаком в конце регулярного выражения.

Если вы не используете не захватывающие скобки, запоминание части совпадения регулярного выражения в обратной ссылке замедляет механизм регулярных выражений, потому что у него больше работы. Если вы не используете обратную ссылку, вы можете ускорить процесс, используя скобки без фиксации, за счет того, что ваше регулярное выражение станет немного труднее читать.

Как использовать обратные ссылки:

Обратные ссылки позволяют повторно использовать часть соответствия регулярному выражению. Вы можете повторно использовать его внутри регулярного выражения или после него.

Что вы сможете с ним делать потом, зависит от инструмента или языка программирования, который вы используете. Чаще всего используется в операциях поиска и замены. В заменяющем тексте будет использоваться специальный синтаксис, позволяющий повторно вставить текст, сопоставленный захваченными группами. Этот синтаксис сильно отличается между различными инструментами и языками, намного больше, чем синтаксис регулярных выражений. Пожалуйста, проверьте замену текстовой ссылки для получения подробной информации.

Использование обратных ссылок в регулярном выражении:

Обратные ссылки можно использовать не только после того, как совпадение было найдено, но и во время совпадения. Предположим, вы хотите сопоставить пару открывающих и закрывающих HTML-тегов и текст между ними.

Например,

grep -E '^.*(\b\w+\b).*\1.*$' language python.md

Он напечатает всю строку, в которой любое слово повторяется внутри строки.

Например, поместив открывающий тег в обратную ссылку, мы можем повторно использовать имя тега для закрывающего тега. Рассмотрим <([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1> регулярное выражение. Это регулярное выражение содержит только одну пару круглых скобок, которые захватывают строку, совпадающую с [A-Z][A-Z0-9]*, в первую обратную ссылку. Эта обратная ссылка используется повторно с \1 (обратная косая черта). / перед ним - это просто косая черта в закрывающем теге HTML, который мы пытаемся сопоставить.

Например,

# Ruby
MAX_ALLOWED_REPETITION = 3
input_roman =~ /(.)\1{#{MAX_ALLOWED_REPETITION},}/

указанное выше условие завершится ошибкой, если строковый объект переменных input_roman имеет шаблон, в котором любой символ повторяется более 3 раз непрерывно.

Чтобы определить номер конкретной обратной ссылки, просканируйте регулярное выражение слева направо и посчитайте открывающиеся круглые скобки. Первая скобка начинается с обратной ссылки номер один, вторая - с цифры два и т. Д. Не фиксирующие скобки не учитываются.

Этот факт означает, что круглые скобки без фиксации имеют еще одно преимущество: вы можете вставлять их в регулярное выражение, не меняя номера, присвоенные обратным ссылкам. Это может быть очень полезно при изменении сложного регулярного выражения.

Использование одной и той же обратной ссылки несколько раз:

Вы можете повторно использовать одну и ту же обратную ссылку более одного раза. ([a-c])x\1x\1 будет соответствовать «axaxa», «bxbxb» и «cxcxc».

Используется последнее сохраненное совпадение:

Механизм регулярных выражений не заменяет постоянно обратные ссылки в регулярном выражении. Он будет использовать последнее совпадение, сохраненное в обратной ссылке, каждый раз, когда его нужно будет использовать. Если новое совпадение найдено путем заключения в круглые скобки, ранее сохраненное совпадение перезаписывается.

Например, посмотрите разницу между ([abc]+) и ([abc])+. Хотя оба успешно соответствуют cab, первое регулярное выражение поместит «cab» в первую обратную ссылку, а второе регулярное выражение будет хранить только «b».

Для получения дополнительной информации см .:

Именованные группы захвата

См .: http://www.regular-expressions.info/ named.html

Группы сброса ветвей

См .: http://www.regular-expressions.info/branchreset.html

Режимы сопоставления регулярных выражений

Большинство обработчиков регулярных выражений поддерживают следующие четыре режима сопоставления:

  • /i делает соответствие регулярного выражения нечувствительным к регистру.
  • /g выполнить глобальное сопоставление (найти все совпадения, а не останавливаться после первого совпадения)
  • /s включает однострочный режим. В этом режиме точка соответствует символу новой строки.
  • /m включает многострочный режим. В этом режиме курсор и доллар совпадают до и после символов новой строки в строке темы.
  • /x включает режим свободного интервала. В этом режиме пробелы между токенами регулярных выражений игнорируются, и неэкранированный # начинает комментарий.

Два языка, которые не поддерживают все четыре вышеперечисленных, - это JavaScript и Ruby. Некоторые разновидности регулярных выражений также имеют дополнительные режимы или параметры, которые имеют однобуквенные эквиваленты. Это очень зависит от реализации.

Модификаторы режима

Обычно режимы сопоставления указываются вне регулярного выражения. В языке программирования вы передаете их как флаг конструктору регулярного выражения или добавляете их к литералу регулярного выражения.

Иногда инструмент или язык не позволяют указать параметры соответствия. В таких ситуациях вы можете добавить модификаторы режима в начало регулярного выражения.

См .: http://www.regular-expressions.info/modifiers.html

Атомная группировка и остальные темы

См .: http://www.regular-expressions.info/atomic.html

Остальные темы из http: //www.regular-expressions оставлены.

Производительность регулярных выражений

Существующий механизм регулярных выражений медленный и может иметь экспоненциальное время работы. Существует реализация с открытым исходным кодом RE2, которая предотвращает медленные совпадения.

Его оболочка Python pre2 (но обратите внимание, что она нестабильна и не обязательно быстрее для каждого конкретного регулярного выражения по сравнению с re). Кроме того, существует оболочка Ruby для старого механизма регулярных выражений safe_regexp, которая не выполняет регулярное выражение, если для этого требуется время, превышающее заданное значение тайм-аута.

Также прочтите Катастрофический возврат.

Рассмотрим следующий пример с использованием re:

import re
template = re.compile("(\w+)+\.")
target = "a"*30
template.search(target)

Здесь для завершения search() требуется несколько минут, а загрузка ЦП достигает 100%. Интересный факт: если строка меньше 20-25 символов, то search() вернется в мгновение ока.

Использование Regex в оболочке Linux

Bash:

Начиная с версии 3, Bash получил собственный оператор RE-match: =~.

См .: http://www.tldp.org/LDP/abs/html/regexp.html

Но я считаю, что самый простой способ использовать grep -E с таким форматом, как:

# prints matched lines with matching words colored
echo "some string in double quotes" | grep --color=always -E "SOME_REGEX_PATTERN"
# prints only matching words
echo "some string in double quotes" | grep --color=always -E "SOME_REGEX_PATTERN" -o

Zsh:

Оператор =~ работает и в Zsh.

использованная литература