Несколько простейших примеров

Regexp Комментарии
/\d\d\d/ Любое трехзначное число ('123', '719', '001')
/\w\s\d\d/ Буква, пробел (или табуляция) и двузначное число ('A 01', 'z 45', 'S 18')
/\d and \d/ Любая из следующих строк: '1 and 2', '9 and 5', '3 and 4'.

Синтаксис регулярных выражений имеет средства для определения собственных подмножеств символов. Например вам может понадобиться задать условие, что в этом месте строки должна находиться шестнадцатиричная цифра или еще что-то подобное. Для описания таких подмножеств применяются символы квадратных скобок '[]'. Квадратные скобки, встреченные внутри регулярного выражения считаются одним символом, который может принимать значения, перечисленные внутри этих скобок.

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

Обратный слэш ('\'). Т.е. все метасимволы из приведенной ранее таблицы будут работать.

Минус ('-'). Используется для задания набора символов из одного промежутка (например все цифры могут быть заданы как '0-9')

Символ '^'. Если этот символ стоит первым в секции задания подмножества символов (и только в этом случае!) он будет рассматриваться как символ отрицания. Т.о. можно задать все символы, которые не описаны в данной секции.

Несколько примеров:

Regexp Комментарии
[0-9A-Fa-f] Цифра в шестнадцатиричной системе счисления
[\dA-Fa-f] То же самое, но с использованием метасимвола
[02468] Четная цифра
[\^d] Все, кроме цифр (аналог метасимвола \D)
[a^b] Любой из символов 'a', 'b', '^'. Заметьте, что здесь символ '^' не имеет какого-либо специального значения, потому что стоит не на первой позиции внутри квадратных скобок.

Теперь необходимо рассмотреть еще несколько метасимволов. Как уже было сказано ранее, все они работают только вне секций описаний подмножеств символов (вне квадратных скобок).

Символы '^' и '{$}'. Они использутся для того, что того, чтобы указать парсеру регулярных выражений на то, чтобы он обратил внимание на положение искомого текста в строке. Символ '^' указывает, что искомый текст должен находиться в начале строки, символ '{$}' наоборот, указывает, что искомый текст должен находиться в конце строки. Посмотрим, как это работает на примере:

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

12 aaa bbbaaa 27 cccaaa aaa 45

И регулярное выражение для поиска чисел в этом тексте: /\d\d/m (не обращайте пока внимания на модификатор). Поиск по этому регулярному выражению вернет нам 3 значения: '12', '27', '45'. Теперь ограничим поиск, указав, где именно внутри строки должен располагаться текст: /^\d\d/m. Здесь результат будет только один - '12', потому что только это число располагается в начале строки. Аналогично, регулярное выражение /\d\d$/m вернет результат '45'.

Символ точки '.'. Этот метасимвол указывает, что на данном месте в строке может находиться любой символ (за исключением символа перевода строки). Очень удобно использовать его, если вам нужно "пропустить" какую-нибудь букву в слове при проверке. Например регулярное выражение /.bc/ найдет в тексте и 'abc' и 'Abc' и 'Zbc' и '5bc'.

Символ вертикальной черты '|'. Используется для задания списка альтернатив. Например регулярное выражение:

/(красное|зеленое) яблоко/

Найдет в тексте все словосочетания 'красное яблоко' и 'зеленое яблоко'.

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

Рассмотрим в качестве примера то, как работает парсер регулярных выражений в случае приведенного выше регулярного выражения о яблоках: /(красное зеленое) яблоко/.

  1. Парсер начинает разбор регулярного выражения и встречает выражение в скобках: (красное|зеленое)
  2. Парсер вызывает себя для поиска по найденному регулярному выражению.
  3. Получив результаты поиска парсер подставляет по очереди каждый из полученных результатов на место выражения в скобках и смотрит, удовлетворяет ли найденный результат всем условиям основного регулярного выражения (в данном случае смотрит, есть ли после найденного слова слово "яблоко").
  4. Если все в порядке - результаты поиска по каждому из имеющихся регулярных выражений для этого случая возвращаются, если нет - парсер просто переходит к следующему найденному фрагменту. Результат поиска внутреннего регулярного выражения для этого фрагмента при этом теряется.

В качестве примера возьмем строку:

яблоко красное и зеленое яблоко и еще одно красноеяблоко и еще одно яблоко, зеленое

Поиск по внутреннему регулярному выражению даст 4 результата (выделены жирным шрифтом):

яблоко красное и зеленое яблоко и еще одно красное яблоко и еще одно яблоко, зеленое

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

яблоко красное и зеленое яблоко и еще одно красное яблоко и еще одно яблоко, зеленое

Необходимо заметить, что для этих двух случаев будет возвращен не только результат поиска по основному регулярному выражению, но и результат поиска по внутреннему регулярному выражению для каждого из найденных фрагментов. В большинстве случаев это полезно (пример - чуть позднее), но иногда наоборот, лучше избавиться от лишних результатов. В этом случае необходимо добавить символы '?:' непосредственно после открывающейся круглой скобки: /(?:красное|зеленое) яблоко/.

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

/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/

Давайте рассмотрим это регулярное выражение подробнее.

Первая круглая скобка здесь теряет свое специальное значение и будет рассматриваться как обычный символ:\(

Далее идет регулярное выражение в скобках (проверка кода города):(\d{3,5})

После этого идет закрывающая круглая скобка, которая также лишена своего специального значения из-за символа обратного слэша, стоящего перед ней:\)

Затем идет пропуск пустого места:\s+

И еще одно регулярное выражение в скобках, которое проверяет номер телефона:(\d{3}-\d{2}-\d{2})

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

Посмотрим, как работает это регулярное выражение. Пусть у нас есть строка: "My phone is (095) 123-45-67". Результатами поиска будут 3 строки: '(095) 123-45-67', '095' и '123-45-67'.

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

Звездочка '*'. Указывает, что символ должен быть повторен 0 или более раз (т.е. символ может отсутствовать или присутствовать в любых количествах). Пример: выражение /ab*c/ найдет строки 'ac', 'abc', 'abbc' и т.д.

Плюс '+'. Указывает, что символ должен быть повторен 1 или более раз (т.е. символ обязан присутствовать и может присутствовать в любых количествах). Пример: выражение /ab+c/ найдет строки 'abc', 'abbc', 'abbbc' и т.д., но не найдет строку 'ac'.

Знак вопроса '?'. Указывает, что символ моет как присутствовать, так и нет, но при этом не может повторяться более одного раза. Пример: выражение /ab?c/ найдет строки 'ac' и 'abc', но не найдет строку 'abbc'.

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

{2,4} - символ должен повториться минимум 2 раза, но не более 4.

{,5} - символ может отсутствовать (т.к. не задано минимальное количество повторений), но если присутствует, то не должен повторяться более 5 раз.

{3,} - символ должен повторяться минимум 3 раза, но может быть и больше.

{4} - символ должен повторяться ровно 4 раза

Есть еще одна тонкость в использовании метасимвола '?'. Посмотрите на такое выражение: /.+a/. Ожидается, что оно вернет нам часть текста до первого вхождения символа 'a' в этот текст. На самом деле оно будет работать несколько не так, как ожидается и результатом поиска будет весь текст до последнего вхождения символа 'a'. Дело в том, что по умолчанию количественные метасимволы "жадничают" и пытаются захватить как можно больший кусок текста. Если это не нужно (как а нашем случае), то необходимо "отучить" их от жадности, указав знак '?' после количественного метасимвола: /.+?a/. После этого выражение будет работать так как надо.

Наши рекомендации