Изучение регулярных выражений [закрыто]

166

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

Teifion
источник

Ответы:

789

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

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

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

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

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

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

Заказать из меню

Добавляя небольшую сложность, вы можете сопоставить 'Nick' или 'Nick' с шаблоном [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 раз, но не более м раз)

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

  • Ик
  • Ник
  • Ник
  • Nnick
  • nNick
  • 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]соответствия «любому пробелу или любому непробелу», другими словами, чему угодно.

Грег Бэкон
источник
14
Вы также можете использовать метод проб и ошибок, и в этом вам может помочь огромная помощь следующих тестеров и отладчиков regex: regex101.com
Juraj.Lorinc,
2
Стоит упомянуть, что, несмотря на то, что это похожий шаблон, a{,m}это не вещь, по крайней мере, в Javascript, Perl и Python.
Фонд Моники иск
2
Было бы очень полезно упомянуть, что существуют разные виды механизмов регулярных выражений, у всех из которых разные наборы функций и синтаксические правила.
hek2mgl
1
hackr.io/tutorials/learn-regular-expressions-regex - отличное место, чтобы найти лучшие онлайн-учебники по регулярным выражениям. Все обучающие материалы здесь представлены и рекомендованы сообществом разработчиков.
Саурабх Худа
2
Цените ваши усилия, чтобы изложить все это в двух словах.
Саураб Тивари