Как новичку разобраться в регулярных выражениях

Синтаксис

Обычные символы (литералы) и специальные символы (метасимволы)

Большинство символов в регулярном выражении представляют сами себя за исключением специальных символов [ ] \ ^ $ . | ? * + ( ) { }, которые могут быть предварены символом \ (обратная косая черта) («экранированы», «защищены») для представления их самих в качестве символов текста. Можно экранировать целую последовательность символов, заключив её между \Q и \E.

Пример Соответствие
a\.? a. или a
a\\\\b a\\b
a\[F\] a[F]
\Q+-*/\E +-*/

Аналогично могут быть представлены другие специальные символы (набор символов, требующих экранирования, может отличаться в зависимости от конкретной реализации). Часть символов, которые в той или иной реализации не требуют экранирования (например, угловые скобки < >), могут быть экранированы из соображений удобочитаемости.

Символьные классы (наборы символов)

Набор символов в квадратных скобках [ ] именуется символьным классом и позволяют указать интерпретатору регулярных выражений, что на данном месте в строке может стоять один из перечисленных символов. В частности, [абв] задаёт возможность появления в тексте одного из трёх указанных символов, а [1234567890] задаёт соответствие одной из цифр. Возможно указание диапазонов символов: например, [А-Яа-я] соответствует буквам русского алфавита.[4]

Если требуется указать символы, которые не входят в указанный набор, то используют символ ^ внутри квадратных скобок, например [^0-9] означает любой символ, кроме цифр.

Добавление в набор специальных символов путём экранирования — самый бесхитростный способ. Однако в современных регулярных выражениях унаследован также и традиционный подход — см. Традиционные регулярные выражения.

Видео

Смотреть вперед

Lookaheads используются, чтобы утверждать, что образец соответствует впереди. Они написаны как(?=pattern)

Давайте использовать его, чтобы исправить наш шаблон:

\b(\w+)(?=\s+a)

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

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

Негативный прогноз утверждает, что его модель не совпадает впереди. Это обозначается как(?!pattern)

Давайте найдем все слова, за которыми не следует слово, начинающееся сa,

\b(\w+)\b(?!\s+a)

Мы сопоставляем целые слова, за которыми не следует пробел иa,

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

Диапазоны символов

Символ точки (.) позволяет нам установить соответствие любому символу. Но иногда нам необходимо быть более конкретными. В этом случае будут полезны диапазоны. Мы указываем диапазон символов, заключая их в квадратные скобки []:

Регулярное выражение: t[eo]d
Пример: When today is over Ted will have a tedious time tidying up.

В регулярном выражении, приведенном выше, мы ищем символ t, за которым следует либо символ e, либо o, и за которым следует символ d.

Количество символов, которые вы можете поместить в квадратные скобки, не ограничено. Вы можете разместить один символ, например, [у] (это было бы немного глупо, но, тем не менее, это не нарушает правила) или вы можете указать несколько символов, например, [Grf4s2 # lknx].

Флаги

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

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

Примечание. Если хотите воспользоваться флагом, выделите регулярное выражение двумя слешами /.

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

  1. g (global) ― не возвращает результат после первого совпадения, а продолжает поиск с конца предыдущего совпадения.
  2. m (multi line) ― с таким флагом, операторы ^ и $ вызовут совпадение в начале и конце строки ввода (line), вместо строки целиком (string).
  3. i (insensitive) ― делает выражение регистронезависимым (например, /aBc/i соответствует AbC).

Если с последним флагом все более-менее понятно, то первые два давайте рассмотрим на примере.

Допустим, у нас есть строка типа:

1‑е место: № 7 ― Тинки-Винки.2‑е место: № 13 ― Лала.3‑е место: № 4 ― По.

И нам нужно найти:

  1. Все цифры

    Шаблон \d, по умолчанию, выдаст нам первое совпадение, то есть «1». Чтобы найти все присутствующие в тексте цифры необходимо подключить флаг глобального поиска — /\d/g, который выдаст нам все совпадения.

  2. Только цифры в начале строки

    Добавить якорь начала строки будет недостаточно. Шаблон ^\d выдаст только «1», глобальный флаг тут не поможет. И это не ошибка. Почему так? Потому что, начало строки в нашем примере действительно только перед единицей, а конец, соответственно, — в самом конце строки:

    ^1–е место: № 7 ― Тинки-Винки2‑е место: № 13 ― Лала3‑е место: № 4 ― По$

    Чтобы считать каждый перенос строки на новую линию «началом», нужно воспользоваться флагом многострочного режима m: шаблону /^\d/gm будут соответствовать «1», «2» и «3», ведь строку такой шаблон будет видеть так:

    ^1е место: № 7 ― Тинки-Винки$^2е место: № 13 ― Лала$^3е место: № 4 ― По$

    Аналогично, можно искать символы с конца строки и линий.

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

Классы символов

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

Класс знаков Описание Шаблон Число соответствий
[ character_group ] Соответствует любому одиночному символу, входящему в character_group. По умолчанию при сопоставлении учитывается регистр. [ae] "a" в "gray" "a", "e" в "lane"
[^ character_group ] Отрицание: соответствует любому одиночному символу, не входящему в character_group. По умолчанию символы в character_group чувствительны к регистру. [^aei] "r", "g", "n" в "reign"
[ first - last ] Диапазон символов: соответствует одному символу в диапазоне от первого до последнего. [A-Z] "A", "B" в "AB123"
. Подстановочный знак: соответствует любому одиночному символу, кроме \n. Для сопоставления символа точки (. или \u002E) перед ней нужно поставить дополнительную обратную косую черту (\.). a.e "ave" в "nave" "ate" в "water"
\p{ имя } Соответствует любому одиночному символу в общей категории Юникода или в именованном блоке, указанном в параметре имя. \p{Lu} \p{IsCyrillic} "C", "L" в "City Lights" "Д", "Ж" в "ДЖem"
\P{ имя } Соответствует любому одиночному символу, не входящему в общую категорию Юникода или в именованный блок, указанный в параметре имя. \P{Lu} \P{IsCyrillic} "i", "t", "y" в "City" "e", "m" в "ДЖem"
\w Соответствует любому алфавитно-цифровому знаку. \w "I", "D", "A", "1", "3" в "ID A1.3"
\W Соответствует любому символу, который не является буквенно-цифровым знаком. \W " ", "." в "ID A1.3"
\s Соответствует любому знаку пробела. \w\s "D " в "ID A1.3"
\S Соответствует любому знаку, не являющемуся пробелом. \s\S " _" в "int __ctr"
\d Соответствует любой десятичной цифре. \d "4" в "4 = IV"
\D Соответствует любому символу, не являющемуся десятичной цифрой. \D " ", "=", " ", "I", "V" в "4 = IV"

Производительность квантификатора

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

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

Специальные символы

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

  • . — одиночный символ

  • [] — набор символов, например [A-Z] обозначает все символы от A до Z

  • ^ — начало строки

  • $ — конец строки

  • \ — экранирование

  • \d — любая цифра

  • \D — все, кроме цифр

  • \s — пробелы

  • \S — все, кроме пробелов

  • \w — буква

  • \W — все, кроме букв

  • [^someSymbol] — отрицание символа, соответсвие всем символам, кроме выбранного

Поговорим об одиночном символе. Это значит, что будет выбираться любой символ, который повторяется только один раз. Например, вернемся к нашей строке Some text и выберем букву t, после которой идет любой символ. Для этого напишем t.

Выберется te, так как после t идет один любой символ (в данном случае е)

Едем дальше. Допустим, у нас есть строка Some text

Едем дальше. Допустим, у нас есть строка Some text12345 и мы хотим выбрать все буквы (только буквы, числа нам не нужны). Для этого мы можем написать следующее [A-Z,a-z] . Что же это значит? Это значит, что мы указали, что мы хотим выбрать все символы в диапазоне от A до Z (это мы выбираем все заглавные буквы) и, затем, через запятую, мы говорим о том, что хотим выбрать все символы от a до z (здесь мы выбираем все строчные символы).

Теперь давайте возьмем слово test и выделим в нем

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

Теперь давайте сделаем наоборот и возьмем последню

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

Перейдем к экранированию. Звучит страшно, но на де

Перейдем к экранированию. Звучит страшно, но на деле все проще простого. Например, в тексте some text. мы хотим выделить точку. Но ведь точка у нас уже зарезервирована как специальный символ (напоминаю, точка обозначает любой одиночный символ). И чтобы сделать так, чтобы точка на считалась как спец. символ мы можем написать \. и тем самым говоря, что точка у нас будет как обычный символ.

Теперь идут, простые вещи. \d у нас обозначает люб

Теперь идут, простые вещи. \d у нас обозначает любую цифру. Например в тексте some text123, если написать \d у нас будут выделяться только цифры.

\D делает все наоборот: берутся все символы, кроме цифр. То есть, если написать \D будет браться все, кроме цифр (и пробелы, кстати, тоже).

\s берет все пробелы, которые есть в строке, а \S — наоборот, все, кроме пробелов.

\w берет буквы, а \W берет, все, кроме букв (в том числе и пробелы).

Теперь расскажу про еще одно применение символа ^. Его можно использовать как отрицание, тем самым исключая символ или группу символов. Например, в слове test мы хотим выбрать все, кроме буквы t и для этого мы можем написать так: [^t]

Именно в такой последовательности символ ^ будет о

Именно в такой последовательности символ ^ будет обозначать отрицание.

Петя любит Дашу.replace(/Дашу

Не трудно догадаться, что результатом работы js-выражения выше будет текст "Петя любит Катю". Даже, если Петя неровно дышит к Маше или Саше, то результат всё равно не изменится.

Рассмотрим базовые спец. символы, которые можно использовать в шаблонах:

СимволОписаниеПример использованияРезультат
\Символ экранирования или начала мета-символа/путь\/к\/папке/Надёт текст путь/к/папке
^Признак начала строки/^Дом/Найдёт все строки, которые начинаются на Дом
$Признак конца строки/родной$/Найдёт все строки, которые заканчиваются на родной
.Точка означает любой символ, кроме перевода строки/Петя ..бит Машу/Найдёт как Петя любит Машу, так и Петя губит Машу
|Означает ИЛИ/Вася|Петя/Найдёт как Васю, так и Петю
?Означает НОЛЬ или ОДИН раз/Вжу?х/Найдёт Вжх и Вжух
*Означает НОЛЬ или МНОГО раз/Вжу*х/Найдёт Вжх, Вжух, Вжуух, Вжууух и т.д.
+Означает ОДИН или МНОГО раз/Вжу+х/Найдёт Вжух, Вжуух, Вжууух и т.д.

Помимо базовых спец. символов есть мета-символы (или мета-последовательности), которые заменяют группы символов:

СимволОписаниеПример использованияРезультат
\wБуква, цифра или _ (подчёркивание)/^\w+$/Соответствует целому слову без пробелов, например _Вася333_
\WНЕ буква, цифра или _ (подчёркивание)/\W\w+\W/Найдёт полное слово, которое обрамлено любыми символами, например @Петя@
\dЛюбая цифра/^\d+$/Соответствует целому числу без знака, например 123
\DЛюбой символ НЕ цифра/^\D+$/Соответствует любому выражению, где нет цифр, например Петя
\sПробел или табуляция (кроме перевода строки)/\s+/Найдёт последовательность пробелов от одного и до бесконечности
\SЛюбой символ, кроме пробела или табуляции/\s+\S/Найдёт последовательность пробелов, после которой есть хотя бы один другой символ
\bГраница слова/\bдом\b/Найдёт только отдельные слова дом, но проигнорирует рядом
\BНЕ граница слова/\Bдом\b/Найдёт только окночние слов, которые заканчиваются на дом
\RЛюбой перевод строки (Unix, Mac, Windows)/.*\R/Найдёт строки, которые заканчиваются переводом строки

Нужно отметить, что спец. символы \w, \W, \b и \B не работают по умолчанию с юникодом (включая кириллицу). Для их правильной работы нужно указывать модификатор u. К сожалению, на окончание 2019 года JavaScript не поддерживает регулярные выражения для юникода даже с модификатором, поэтому в js эти мета-символы работают только для латиницы.

Ещё регулярные выражения поддерживают разные виды скобочек:

ВыражениеОписаниеПример использованияРезультат
(…)Круглые скобки означают под-шаблон, который идёт в результат поиска/(Петя|Вася|Саша) любит Машу/Найдёт всю строку и запишет воздыхателя Маши в результат поиска под номером 1
(?:…)Круглые скобки с вопросом и двоеточием означают под-шаблон, который НЕ идёт в результат поиска/(?:Петя|Вася|Саша) любит Машу/Найдёт только полную строку, воздыхатель останется инкогнито
(?P<name>…)Задаёт имя под-шаблона/(?P<воздыхатель>Петя|Вася|Саша) любит Машу/Найдёт полную строку, а воздыхателя запишет в результат под индексом 1 и ‘воздыхатель’
[abc]Квадратные скобки задают ЛЮБОЙ СИМВОЛ из последовательности (включая спец. символы \w, \d, \s и т.д.)/^[123]+$/Соответствует любому выражению 323323123, но не 54321
[a-я0-9]Если внутри квадратных скобок указать минус, то это считается диапазоном/[A-Za-zА-Яа-яЁё0-9_]+/Аналог /\w/ui для JavaScript
[abc-]Если минус является первым или последним символом диапазона, то это просто минус/[0-9+-]+/Найдёт любое целое числое с плюсом или минусом (причём не обязательно, чтобы минус или плюс были спереди)
[^…]Квадратные скобки с «крышечекой» означают любой символ НЕ входящий в диапазон/[^a-zа-я0-9 ]/iНайдёт любой символ, который не является буквой, числом или пробелом
[[:class:]]Квадратные скобки в квадратных скобках задают класс символов (alnum, alpha, ascii, digit, print, space, punct и другие)/[^[:print:]]+/Найдёт последовательность непечатаемых символов
{n}Фигурные скобки с одним числом задают точное количество символов/\w+н{2}\w+/uНайдёт слово, в котором две буквы н
{n,k}Фигурные скобки с двумя числами задают количество символов от n до k/\w+н{1,2}\w+/uНайдёт слово, в котором есть одна или две буквы н
{n,}Фигурные скобки с одним числом и запятой задают количество символов от n до бесконечности/\w+н{3,}\w+/uНайдёт слово, в котором н встречается от трёх и более раз подряд

Работа с Регулярными Выражениями

Регулярные выражения используются в методах test и exec объекта RegExp и с методами match, replace, search, и split объекта String. Эти методы подробно объясняются в Справочнике JavaScript.

Чтобы просто узнать есть ли в строке что либо соответствующее шаблону, воспользуйтесь методами test или search; а чтобы получить больше информации пользуйтесь методами exec или match (хотя эти метода работают медленнее). Если вы пользуетесь exec или match и если совпадения есть, эти методы вернут массив и обновлённые свойства объекта ассоциированного регулярного выражения а также предопределённого объекта RegExp регулярного выражения. Если совпадений нет, метод exec вернёт null (который сконвертируется в  false).

В след. примере, скрипт использует метод exec чтобы найти совпадения в строке.

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

var myArray = /d(b+)d/g.exec(«cdbbdbsbz»);

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

Использование скобок в шаблоне регулярного выражения повлечёт «запоминание» совпавшей подстроки. Для примера, /a(b)c/ вызовет совпадение ‘abc’ и запомнит ‘b’. Чтобы получить совпадения скобочного выражения используйте Array elements [1], …, [n].

Расширенный поиск с флагами

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

Флаги регулярных выражений
Flag Description
g Глобальный поиск.
i Регистронезависимый поиск.
m Многострочный поиск.
y Выполняет поиск начиная с символа, который находится на позиции свойства lastindex текущего регулярного выражения.

Чтобы использовать флаги в шаблоне регулярного выражения используйте следующий синтаксис:

или

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

Для примера, re = /\w+\s/g создаёт регулярное выражение, которое ищет один или более символов, после которых следует пробел и ищет данное совпадение на протяжении всей строки.

Выведет  [«fee «, «fi «, «fo «]. В этом примере вы бы могли заменить строку:

на следующую:

и получить тот же результат.

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

Экранирование

Иногда нам может потребоваться найти один из символов, который является метасимволом. Для этого мы используем то, что называется экранированием. Поместив обратную косую черту (\) перед метасимволом, мы можем удалить его особое значение. Допустим, что нам нужно найти появление слова this, которое является последним словом в предложении.

Если бы мы сделали следующее:

Регулярное выражение: this.
Пример: Surely this regular expression should match this.

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

Решением будет следующее:

Регулярное выражение: this\.
Пример: Surely this regular expression should match this.

Совет: Когда метасимволы являются частью вашей искомой строки, то очень легко забыть об их экранировании. Если в результатах ваших регулярных выражений что-то не так, то внимательно обследуйте метасимволы, которые вы, возможно, забыли экранировать.

Прочие конструкции

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

Конструкция Определение Пример
(?imnsx-imnsx) Устанавливает или отключает такие параметры, как учет регистра в середине шаблона. Дополнительные сведения см. в статье Параметры регулярных выражений. \bA(?i)b\w+\b соответствует "ABA", "Able" в "ABA Able Act"
(?# comment ) Встроенное примечание. Примечание заканчивается первой закрывающей скобкой. \bA(?#Matches words starting with A)\w+\b
# [до конца строки] Комментарий режима X. Примечание начинается от знака без обратной косой черты и продолжается до конца строки. (?x)\bA\w+\b#Matches words starting with A

Теги