Сведения о вопросе

GANGST1ER

16:03, 1st July, 2020

Теги

regex    

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

Просмотров: 584   Ответов: 1

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



  Сведения об ответе

PROGA

18:03, 1st July, 2020

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

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

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

Концептуально простейшими регулярными выражениями являются литеральные символы. Шаблон N соответствует символу 'N'.

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

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

Заказ из меню

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

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

Представьте себе классы символов как меню: выберите только один.

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

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

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

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

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

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

Собирая некоторые из этих блоков вместе, шаблон [Nn]*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 . Круглые скобки обозначают подшаблон, который можно количественно определить как единицу измерения. Кроме того, обычно для обработчиков регулярных выражений используется сохранение или "capture" части входного текста, которая соответствует группе скобок. Извлечение битов таким способом гораздо более гибко и менее подвержено ошибкам, чем подсчет индексов и substr .

Чередование

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

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

Убегающий

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

Жадность

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

Например, скажем, что входной сигнал является

"Hello," она сказала: "How are you?"

Вы можете ожидать, что ".+" будет соответствовать только "Привет", а затем будете удивлены, когда увидите, что он соответствует от 'Hello' до самого конца " вы?".

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

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

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

Бросить якорь

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

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

-- This is a comment --

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

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

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

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

Книги

Свободные ресурсы

Сноска

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться