Теория

Parent Previous Next

Регуля́рные выраже́ния (англ. regular expressions, сокр. RegExp, RegEx, жарг. регэ́кспы или ре́гексы) — это формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов (символов-джокеров, англ. wildcard characters). По сути это строка-образец (англ. pattern, по-русски её часто называют «шаблоном», «маской»), состоящая из символов и метасимволов и задающая правило поиска.


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


Базовые понятия


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


Большинство букв и символов соответствуют сами себе. Например, регулярное выражение test будет в точности соответствовать строке test (программа Datacol использует режим без учета регистра, что позволит этому регулярному выражению также соответствовать Test или TEST).


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


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

. ^ $ * + ? { [ ] \ | ( )


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

Например, [abc] будет соответствовать любому из символов a, b или c; это то же самое, что выражение [a-c], использующее диапазон для задания того же множеств символов. Если вы хотите сопоставить только строчные буквы, регулярное выражение будет иметь вид [a-z].


Метасимволы не активны внутри классов. Например, [akm$] будет соответствовать любому из символов 'a', 'k', 'm' или '$'. Знак '$' это обычно метасимвол (как видно из списка символов выше), но внутри класса символов он лишается своей особой природы.


Для того, чтобы находить соответствие символам вне этого класса, в начале класса добавляется символ '^'. Например, выражение [^5] соответствует любому символу, кроме '5'.


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


Некоторые из специальных последовательностей, начинающихся с '\' представляют предопределенные наборы символов, часто бывающие полезными, такие как набор цифр, набор букв, или множества всего, что не является пробелами, символами табуляции и т. д. (whitespace). Следующие предопределенные последовательности являются их подмножеством:

\d

Соответствует любой цифре; эквивалент класса [0-9].

\D

Соответствует любому нечисловому символу; эквивалент класса [^0-9].

\s

Соответствует любому символу whitespace; эквивалент [ \t\n\r\f\v].

\S

Соответствует любому не-whitespace символу; эквивалент [^ \t\n\r\f\v].

\w

Соответствует любой букве или цифре; эквивалент [a-zA-Z0-9_].

\W

Наоборот; эквивалент [^a-zA-Z0-9_].


Эти последовательности могут быть включены в класс символов. Например, [\s,.] является характер класс, который будет соответствовать любому whitespace-символу или запятой или точке.


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


Повторяющиеся наборы символов


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


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


Например, ca*t будет соответствовать ct (0 символов a), cat (1 символ a), caaat (3 символа a), и так далее.


Повторения, такие как * называют жадными (greedy); движок будет пытаться повторить его столько раз, сколько это возможно. Если следующие части шаблона не соответствуют, движок вернется назад и попытается попробовать снова с несколькими повторами символа.


Пошаговое рассмотрение какого-нибудь примера сделает объяснение более ясным. Давайте рассмотрим выражение a[bcd]*b. Оно соответствует букве 'a', нулю или более символов из класса [bcd], и наконец, заключительной букве 'b'. Теперь представим себе сопоставление этого регулярного выражения строке abcbd. Вот как происходит сравнение поэтапно:

1. a — 'a' соответствует регулярному выражению

2. abcbd — движок сопоставляет [bcd]* на как можно большем числе символов, то есть до конца строки (поскольку все символы соответствуют классу в скобках [])

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

4. abcb — вернулись назад, уменьшили на один символ сопоставление с [bcd]*

5. Провал — пытаемся снова найти b, но в конце только d

6. abc — снова возвращаемся назад, теперь [bcd]* это только bc

7. abcb — снова ищем последний символ регулярного выражения — b. Теперь он действительно находится на нужной позиции и мы добиваемся успеха



Итак, был достигнут конец регулярного выражения и сопоставление с ним дало abcb. Этот пример показал, как движок сначала забирается так далеко, как может, и, если не находит соответствия, возвращается назад, снова и снова работая с остатком регулярного выражения. Он будет делать так до тех пор, пока не получит ноль совпадений для [bcd]*, и, если и тогда не получится совпадения, то заключит, что строка совсем не соответствует шаблону регулярного выражения.


Другой метасимвол повторения это +, повторяющий последовательность сравнения один или более раз. Обратите особое внимание на разницу между * и +. * требует соответствия необходимой части ноль или более раз, то есть повторяемое может и не присутствовать вовсе, а + требует, по крайней мере одно вхождение. Для аналогичного примера ca+t будет сопоставляться cat или, например, caaat, но никак не ct.


Есть еще два повторяющих спецификатора. Знак вопроса, ?, проверяющий наличие совпадения ноль или один раз. Например, home-?brew соответствует как homebrew, так и home-brew.


Наиболее полный повторяющий спецификатор это {m,n}, где m и n — целые числа. Этот определитель означает, что здесь должно быть не менее m и не более n повторений. Например, a/{1,3}b соответствует a/b, a//b и a///b. Это не может быть ab, строка в которой нет слэшей или a////b, в которой их четыре.


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


Читатели уже могли заметить, что все три остальных спецификатора могут быть выражены через последний. {0,} это то же, что *, {1,} эквивалентно +, и {0,1} может заменять знак ?.

Created with the Personal Edition of HelpNDoc: Full-featured Help generator