Регулярные выражения, или Regular Expressions, существуют во всех языках программирования. В них отличаются методы для работы с регулярными выражениями, но синтаксис остается одинаковым. Поэтому здесь мы сосредоточимся именно на общем синтаксисе, а не на примерах использования в конкретном языке.
С моей точки зрения, регулярные выражения не являются очень простой темой для понимания, т.к. в обилии символов, квантификаторов и групп довольно сложно разобраться, особенно при первом столкновении. Однако иногда нет другого способа быстро решить задачу, кроме как использовать регулярное выражение.
Коль вы попали на эту страницу, наверняка вы уже понимаете, что "регулярки" работают со строками. Поэтому и синтаксис их, в первую очередь, связан с различными символами. По сути своей регулярные выражения представляют собой некие шаблоны для поиска и замены их в строке/тексте. Кстати, в HTML-формах регулярные выражения могут использоваться в качестве значения для атрибута pattern
в любом текстовом поле (теги <input>
или <textarea>
).
Синтаксис регулярного выражения, который поддерживается большинством языков программирования, выглядит так:
1 | /шаблон/модификатор(ы) |
Здесь мы будем рассматривать примеры регулярных выражений для JavaScript и PHP.
Для начала, давайте рассмотрим, что может входить в группу символов.
Классы символов
Итак, первый разбор синтаксиса регулярных выражений посвящен символам:
Выражение | Назначение (что делает) |
---|---|
[abc] | Соответствует любому из символов a, b или c. |
[^abc] | Соответствует любому символу, кроме a, b или c. |
[a-z] | Соответствует любому символу в нижнем регистре a до нижнего регистра z. |
[A-Z] | Соответствует любому символу в верхнем регистре a до верхнего регистра Z. |
[a-Z] | Соответствует любому символу от нижнего регистра a до верхнего регистра Z. |
[0-9] | Соответствует одной цифре от 0 до 9. |
[a-z0-9] | Соответствует одному символу от a до z или от 0 до 9. |
(x|y) | Любой из вариантов, разделенных символом | (или x, или y) |
Квадратные скобки, в которых заключен шаблон символов, называются классом символов, например [abc]
. Класс символов всегда соответствует одному символу из списка указанных символов, что означает, что выражение [abc]
соответствует только символу a, b
или c
.
Также можно определить классы отрицательных символов, которые соответствуют любому символу, кроме тех, которые содержатся в скобках. Класс отрицательных символов определяется путем размещения ^
символа каретки ( ) сразу после открывающей скобки, например [^abc]
:
Вы также можете определить диапазон символов, используя -
символ дефиса (-
) внутри класса символов, например [0-9]
.
Например, если нам нужно заменить целое слово, то в качестве регулярного выражения указывается оно:
1 2 3 4 5 | <?php $str = 'Baby monkey loves his mother monkey'; $strReplace = preg_replace('/monkey/', 'frog', $str); //Вывод: Baby-frog loves its mother frog echo "<p>$strReplace</p>"; ?> |
Если же нужно выбрать несколько каких-то символов , то мы можем их указать в квадратных скобках:
1 2 3 4 5 6 7 | <?php $str = 'Baby monkey loves his mother monkey'; $strReplace = preg_replace('/[mnk]/', '<span style="color: red">t</span>', $str); echo "<p>$strReplace</p>"; // вывод Baby tottey loves his tother tottey с красными символа ми t ?> |
Если нас интересует замена всех согласных символов, то проще указать диапазон символов, которые нужно исключить из выборки [^aeoyi]
:
1 2 3 4 5 6 7 | <?php $str = 'Hello beautiful world!'; $strReplace = preg_replace('/[^aeoyi]/', '<b>m</b>', $str); echo "<p>$strReplace</p>"; //вывод memmommeammimmmmmommmm ?> |
Что касается чисел, то с помощью шаблона [0-9]
мы будем искать каждую новую цифру:
1 2 3 4 5 6 7 8 | <?php $str = 'Битва под Ватерлоо произошла 18 июня 1815 года.'; $strReplace = preg_replace('/[0-9]/', '<b>0</b>', $str); echo "<p>$strReplace</p>"; //Вывод: Битва под Ватерлоо произошла <b>0</b><b>0</b> июня <b>0</b><b>0</b><b>0</b><b>0</b> года. ?> |
Все примеры, которые здесь будут приводиться, вы можете протестировать на сайтах phpliveregex или regex101.com.
Сами примеры работают на основе PHP, т.к. в сможете сразу их проверить в онлайн-песочнице.
Предопределенные классы символов
Некоторые классы символов, такие как цифры, буквы и пробелы, используются настолько часто, что для них существуют сокращенные имена. В следующей таблице перечислены эти предопределенные классы символов:
Класс | Назначение (что делает) |
---|---|
. | Соответствует любому одиночному символу, кроме символа новой строки \n . |
\d | соответствует любому цифровому символу. Такой же как [0-9] |
\D | Соответствует любому нецифровому символу. Такой же как[^0-9] |
\s | Соответствует любому символу пробела (пробелу, табуляции, новой строке или символу возврата каретки). Такой же как[ \t\n\r] |
\S | Соответствует любому символу без пробелов. Такой же как[^ \t\n\r] |
\w | Соответствует любому символу слова (определяемому как от a до z, от A до Z, от 0 до 9 и знака подчеркивания). Такой же как [a-zA-Z_0-9] |
\W | Соответствует любому символу, не являющемуся словом. Такой же как[^a-zA-Z_0-9] |
Поскольку в обоих текстах есть некие повторения и разный регистр символов, сразу же еще часть теории, без которой будет сложно рассматривать примеры - о модификаторах.
Экранирование символов
Нужно еще помнить о том, что регулярные выражения могут быть совсем не простыми, они могут иметь группы, диапазоны символов или диапазоны количества символов, поэтому часть символов необходимо экранировать с помощью обратного слэша.
Это такие символы:
1 | ^ $ \ . * + ? ( ) [ ] { } | |
Здесь мы рассмотрим пример, связанный не только с экранированием, но и со скобочными группами. Будем выполнять проверку телефонного номера. В примере регулярное выражение const re = /\(?\d{3}\)?([-| ]+)\d{3}\1+\d{4}/;
подразумевает, что мы можем использовать или опустить круглые скобки для кода города из 3-х цифр. Сам символ скобки выглядит, как \(
или \)
. А вот то, что мы можем его указать или опустить, оформляется символом в виде вопросительного знака \(?
, который относится к операторам повторения.
Вторые скобки ([-| ]+)
здесь уже выступают в виде спецсимвола, или оператора, формирующего скобочную группу. Причем эта группа должна повториться перед второй группой цифр, что обозначается цифрой один - \d{3}\1
. То есть первая группа в скобках запоминается, и затем может быть использована под цифрой 1. Поэтому в телефонном номере нужно либо ставить черточки между цифрами, либо пробелы. И то, и другое совмещать нельзя - это приведет к ошибке.
See the Pen Phone Number Validate by Elen (@ambassador) on CodePen.
Другой пример с использованием скобочных групп вы найдете ниже.
Модификаторы (флаги) шаблонов
Модификатор шаблона позволяет вам контролировать способ обработки совпадения с шаблоном. Они размещаются в синтаксисе регулярного выражения после второго слеша. Например, если вы хотите выполнить поиск по шаблону без учета регистра символов, вы можете использовать модификатор i
следующим образом: /pattern/i
. В таблице ниже перечислены некоторые наиболее часто используемые модификаторы шаблонов.
Модификаторы также называют флагами, поэтому вы можете использовать любое из этих названий.
Модификатор/ флаг | Назначение (что делает) |
---|---|
i | Проверяет текст на совпадение без учета регистра. |
g | Выполняет глобальное сопоставление, т. е. находит все вхождения шаблона в тексте или строке. |
m | Изменяет поведение и для соответствия границе новой строки (т. е. началу или концу каждой строки в многострочной строке), а не границе строки. Определяет текст как множество строк и ищет совпадения маркеров ^ , $ для каждого начала и конца строки в тексте. |
В JavaScript | |
y | Выполняет поиск начиная с символа, который находится на позиции свойства lastindex текущего регулярного выражения. |
u | запись в регулярное выражение Unicode. |
В PHP | |
s | Изменяет поведение (точки) для соответствия всем символам, включая символы новой строки. |
x | Позволяет использовать пробелы и комментарии внутри регулярного выражения для ясности. |
Операторы в регулярных выражениях
Операторы позволяют указать, что регулярное выражение должно начинаться или заканчиваться определенными символами, позволяет выделать их в группы или указывать на то, что символ либо может быть, либо может отсутствовать.
Оператор | Назначение (что делает) |
---|---|
^ | Указывает на начало строки. |
$ | Указывает на конец строки. |
. | соответствует любому символу кроме переноса строки. |
(xyz) | Соответствует 'xyz' и запоминает это соответствие. Выделяет соответствие в группу |
(?:x) | Соответствует 'x' но не запоминает соответствие. Это называется незахватывающие скобки. Сопоставленная строка не может быть получена из элементов результирующего массива [1], ..., [n]. |
x(?=y) | Соответствует 'x' только если за 'x' следует 'y' (т.н. упреждение). Выделяет соответствие в группу |
x(?!y) | Соответствует 'x', за которым не следует 'y'. |
Операторы повторения
Довольно часто нам нужно указать, что количество символов не может быть больше или меньше определенного диапазона. В этом случае в фигурных скобках после символа или группы символов мы указываем количество повторений.
Оператор | Назначение (что делает) | Пример | Подходящие строки |
---|---|---|---|
{2} | повторяется ровно 2 раза | \d{2} | 22, ata56ata |
{n} | повторяется ровно n раз | \d{2} | 22, ata56ata |
{n,m} | повторяется от n до m раз | \d{2,4} | 221, ata56ata3564 |
{n,} | повторяется не менее n раз | \d{2,} | 134722, ata56ata21 |
{,m} | повторяется не более m раз | \d{,3} | 722, ata56ata1 |
Здесь следует отметить, что оператор применяется только к тому символу, который расположен перед ним.
Кроме того, мы можем указать, сколько раз данный символ может встретиться:
Оператор | Аналог | Значение |
---|---|---|
? | {0,1} | Ноль (ни одного) или одно вхождение |
* | {0,} | Ноль или более вхождений. |
+ | {1,} | Одно или более вхождений. |
Скобочные группы
Скобки вокруг любой части регулярного выражения означают, что эта часть исследуемой подстроки будет запомнена.
Скобочные группы предназначены для того, чтобы либо найти некую повторяемость символов, либо чтобы иметь возможность совпадающие с шаблонными группами части строк поменять местами или преобразовать любым другим доступным образом.
Например, у нас есть задача поменять местами имя и фамилию некоего человека, заменив пробел между ними запятой. В данном случае скобочной группой будет использование символа слова \w
в английском варианте и набора кириллических букв в русском. Универсальный шаблон подразумевает, что он должен работать и для латинских, и для русских, и для украинских букв. Плюс еще мы учитываем, что имена могут бить вроде Лиза-Мария, а фамилии - типа O'Hara или Квітка-Основ'яненко.
Одной скобочной группой у нас будет использование как минимум одного символа из набора букв в первой скобке, затем у нас идет пробельный символ в виде \s
и вторая группа тоже с минимально одним символом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const reEng = /(\w+)\s([\w']+)/i, reRus = /([а-яё]+)\s([а-яё]+)/i, reUni = /([\wа-яёіїє']+)\s([\wа-яёіїє'-]+)/i; let strRus = "Григорий Сковорода"; let strEng = "Nally O'Hara"; let strUkr = "Григорій Квітка-Основ'яненко"; document.write(`<p><i>${strEng}</i> преобразована в <b>${strEng.replace(reEng, "$2, $1")}</b></p>`); document.write(`<p><i>${strEng}</i> преобразована в <b>${strEng.replace(reRus, "$2, $1")}</b></p>`); document.write(`<p><i>${strRus}</i> преобразована в <b>${strRus.replace(reEng, "$2, $1")}</b></p>`); document.write(`<p><i>${strRus}</i> преобразована в <b>${strRus.replace(reRus, "$2, $1")}</b></p>`); document.write(`<p><i>${strUkr}</i> преобразована в <b>${strUkr.replace(reUni, "$2, $1")}</b></p>`); document.write(`<p><i>${strEng}</i> преобразована в <b>${strEng.replace(reUni, "$2, $1")}</b></p>`); document.write(`<p><i>${strRus}</i> преобразована в <b>${strRus.replace(reUni, "$2, $1")}</b></p>`); |
Вот, что выведет пример:
И обратный вариант преобразования строк с заменой символьных групп:
1 2 3 | console.log( "Hopper, Grace\nMcCarthy, John\nRitchie, Dennis" .replace(/([\w ]+), ([\w ]+)/g, "$2 $1")); |
В консоли увидим:
1 2 3 | Grace Hopper John McCarthy Dennis Ritchie |
Для того, чтобы сопоставить подстроку без вызова совпавшей части для запоминания, внутри круглых скобок необходимо предварить паттерн сочетанием символов ' ?:'
. Например, шаблон (?:\d+)
будет соответствовать одному или более цифровому символу, но не запомнит совпавших символов.
Примеры использования регулярных выражений
Валидация email, пароля и повторения пароля на JS
See the Pen Validate Email & Password (JS) by Elen (@ambassador) on CodePen.