Изучение регулярных выражений

Я не очень понимаю регулярные выражения. Можете ли вы объяснить их мне простым и понятным языком? Если есть какие-либо онлайн-инструменты или книги, не могли бы вы также дать на них ссылку?

Ответов (1)

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

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

Начни с простого

По сути, простейшие регулярные выражения - это буквальные символы. Шаблон N соответствует символу «N».

Регулярные выражения рядом друг с другом соответствуют последовательностям. Например, шаблон Nick соответствует последовательности «N», за которой следует «i», за которым следует «c», за которым следует «k».

Если вы когда-либо использовали grep Unix - пусть даже только для поиска обычных строк - вы уже использовали регулярные выражения! (The re в grep относится к регулярным выражениям.)

Заказ из меню

Добавив немного сложности, вы можете сопоставить с шаблоном «Ник» или «ник» [Nn]ick . Часть в квадратных скобках - это класс символов , что означает, что он соответствует ровно одному из заключенных символов. Вы также можете использовать диапазоны в классах символов, поэтому [a-c] соответствует либо «a», либо «b», либо «c».

Шаблон . особенный: он соответствует не только буквальной точке, а любому символу . Концептуально это то же самое, что и действительно большой класс персонажей [-.?+%$A-Za-z0-9...] .

Думайте о классах персонажей как о меню: выберите только один.

Полезные ярлыки

Использование . может сэкономить вам много времени на набор текста, и есть другие ярлыки для общих шаблонов. Допустим, вы хотите сопоставить цифру: это один из способов написать [0-9] . Цифры часто совпадают, поэтому вместо них вы можете использовать ярлык \d . Другие - \s (пробел) и \w (символы слова: буквенно-цифровые символы или подчеркивание).

В верхнем регистре варианты их комплементы, поэтому \S соответствует любому нон -whitespace характер, например.

Один раз недостаточно

Оттуда вы можете повторять части вашего шаблона с квантификаторами . Например, шаблон ab?c соответствует 'abc' или 'ac', потому что ? квантификатор делает подшаблон, который он модифицирует, необязательным. Другие кванторы:

  • * (ноль или более раз)
  • + (один или несколько раз)
  • {n}(ровно n раз)
  • {n,}(не менее n раз)
  • {n,m}(не менее n раз, но не более m раз)

Собирая некоторые из этих блоков вместе, шаблон [Nn]*ick соответствует всем

  • ick
  • Ник
  • Ник
  • Нник
  • nNick
  • нник
  • (и так далее)

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

Еще несколько полезных примеров:

  • [0-9]+(и его эквивалент \d+) соответствует любому неотрицательному целому числу
  • \d{4}-\d{2}-\d{2} соответствует датам в формате 2019-01-01

Группировка

Квантификатор изменяет образец слева от него. Вы можете ожидать 0abc+0 совпадения '0abc0', '0abcabc0' и т. Д., Но образец, расположенный непосредственно слева от квантификатора плюса, соответствует c . Это означает 0abc+0 соответствие '0abc0', '0abcc0', '0abccc0' и так далее.

Чтобы сопоставить одну или несколько последовательностей abc с нулями на концах, используйте 0(abc)+0 . Скобки обозначают подшаблон, который можно количественно выразить как единицу. Механизмы регулярных выражений также часто сохраняют или «захватывают» ту часть входного текста, которая соответствует группе в скобках. Извлечение битов таким способом гораздо более гибкое и менее подверженное ошибкам, чем подсчет индексов и substr .

Чередование

Ранее мы видели один способ сопоставить «Ник» или «ник». Другой - с чередованием как в Nick|nick . Помните, что чередование включает все, что находится слева, и все, что справа. Использование группирования скобки для ограничения объема |, например , (Nick|nick) .

В другом примере вы могли бы эквивалентно написать [a-c] как a|b|c, но это, вероятно, будет неоптимальным, потому что многие реализации предполагают, что альтернативы будут иметь длину больше 1.

Побег

Хотя некоторые символы соответствуют друг другу, другие имеют особое значение. Шаблон \d+ не соответствует обратной косой черте, за которой следует строчная буква D, за которой следует знак плюса: чтобы получить это, мы использовали бы \\d\+ . Обратная косая черта удаляет особое значение следующего символа.

Жадность

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

Например, предположим, что ввод

«Привет, - сказала она, - как дела?»

Вы можете ожидать, что ".+" будет соответствовать только «Hello», и затем будете удивлены, когда увидите, что оно соответствует от «Hello» до «you?».

Чтобы переключиться с жадности на то, что вы считаете осторожным, добавьте ? в квантификатор дополнительную величину. Теперь вы понимаете, как работает \((.+?)\) пример из вашего вопроса. Он соответствует последовательности буквальной левой круглой скобки, за которой следует один или несколько символов и заканчивается правой круглой скобкой.

Если вы введете «(123) (456)», то первый захват будет «123». Нежадные квантификаторы хотят, чтобы остальная часть шаблона начала сопоставление как можно скорее.

(Что касается вашего недоразумения, я не знаю ни одного диалекта регулярных выражений, на котором можно ((.+?)) было бы сделать то же самое. Я подозреваю, что что-то потерялось при передаче где-то по пути.)

Якоря

Используйте специальный шаблон ^ для сопоставления только в начале вашего ввода и $ для сопоставления только в конце. Создание «подставок для книг» с вашими выкройками, когда вы говорите: «Я знаю, что спереди и сзади, но дайте мне все, что находится между ними» - полезная техника.

Допустим, вы хотите сопоставить комментарии формы

-- This is a comment --

ты бы написал ^--\s+(.+)\s+--$ .

Построй свой собственный

Регулярные выражения рекурсивны, поэтому теперь, когда вы понимаете эти основные правила, вы можете комбинировать их, как хотите.

Инструменты для написания и отладки регулярных выражений:

Книги

Бесплатные ресурсы

Сноска

†: Приведенное выше утверждение, которое . соответствует любому символу, является упрощением для педагогических целей, что не совсем верно. Точка соответствует любому символу, кроме символа новой строки, "\n" но на практике вы редко ожидаете, что шаблон, например, .+ пересечет границу новой строки. В регулярных выражениях Perl есть /sпереключатель, а в Java Pattern.DOTALL, например, можно . вообще сопоставить любой символ. Для языков, в которых нет такой функции, вы можете использовать что-то вроде [\s\S] поиска «любых пробелов или любых непробельных символов», другими словами, что угодно.