Сообщить об ошибке.

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

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

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

Например, ca*t будет соответствовать ct - 0 символов a, cat - 1 символ a, caaat - 3 символа a и т. д. Движок регулярных выражений имеет различные внутренние ограничения, связанные с размером типа int языка C, что не позволяет ему сопоставлять более 2 миллиардов aсимволов. Шаблоны поиска обычно не пишутся, чтобы соответствовать такому количеству данных.

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

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

Операции, производимые движком регулярных выражений.

  1. a - a в совпадает с шаблоном поиска.
  2. abcbd - поиск повторов [bcd]* идет так далеко, как может, до конца строки.
  3. сбой - движок пытается найти соответствие b, но текущая позиция находится в конце строки, поэтому он терпит неудачу.
  4. abcb - движок делает резервную копию, чтобы [bcd]* соответствовал на один символ меньше.
  5. сбой - движок пробует еще раз найти соответствие b, но текущая позиция находится на последнем символе, который является d.
  6. abcb - движок делает резервную копию еще раз, так что [bcd]* соответствует только bc.
  7. abcb - движок снова пробует найти соответствие b. На этот раз символ в текущей позиции 'b'.
  8. abcb - соответствие найдено.

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

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

Есть еще два квантификатора для повторений. Знак вопроса ?, который соответствует совпадению одного символа или нулю совпадений символа, после которого он стоит. Об этом можно думать как о пометке чего-то, что является необязательным. Например, шаблон поиска home-?brew соответствует либо homebrew или home-brew.

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

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

Можно заметить, что все три других квантификатора могут быть выражены с помощью нотации {m,n}. Звездочка '*' может быть выражена при помощи {0,}, что '+' эквивалентно {1,}, а {0,1} то же самое, что и '?'. Лучше использовать '*', '+' или '?' когда это возможно просто потому, что они короче и при этом шаблоны регулярных выражений легче читать.