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

Aug 07 2008

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

Ответы

802 GregBacon May 03 2010 at 23:09

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

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

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

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

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

Если вы когда-либо использовали grepUnix - пусть даже только для поиска обычных строк - вы уже использовали регулярные выражения! (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+--$.

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

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

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

  • RegExr (для JavaScript)
  • Perl: YAPE: Regex Explain
  • Regex Coach (движок, поддерживаемый CL-PPCRE )
  • RegexPal (для JavaScript)
  • Онлайн-тестер регулярных выражений
  • Регулярное выражение Бадди
  • Regex 101 (для PCRE, JavaScript, Python, Golang)
  • Визуальный RegExp
  • Expresso (для .NET)
  • Rubular (для Ruby)
  • Библиотека регулярных выражений (предопределенные регулярные выражения для распространенных сценариев)
  • Txt2RE
  • Тестер регулярных выражений (для JavaScript)
  • Regex Storm (для .NET)
  • Debuggex (визуальный тестер регулярных выражений и помощник)

Книги

  • Освоение регулярных выражений , 2-е и 3-е издание .
  • Памятка по регулярным выражениям
  • Поваренная книга регулярных выражений
  • Научитесь регулярным выражениям

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

  • RegexOne - учитесь с помощью простых интерактивных упражнений.
  • Регулярные выражения - все, что вам следует знать (серия PDF)
  • Сводка синтаксиса регулярных выражений
  • Как работают регулярные выражения

Сноска

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