Статьи

Демистификация RegEx с практическими примерами

Регулярное выражение — это последовательность символов, используемая для анализа и манипулирования строками. Они часто используются для поиска, замены подстрок и проверки строковых данных. В этой статье приводятся советы, рекомендации, ресурсы и инструкции по прохождению сложных регулярных выражений.

regular expression

Существует множество книг, статей, веб-сайтов и официальной документации PHP , в которых объясняются регулярные выражения, поэтому вместо написания другого объяснения я бы предпочел перейти непосредственно к более практичным примерам. Вы можете найти полезную шпаргалку по этой ссылке .

Наряду с множеством полезных ресурсов, в нижней части этого поста также есть видео с конференции Леа Веру, которое немного длинное, но отлично справляется с разрушением RegEx.

Как построить хорошее регулярное выражение

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

1. Определите сценарий

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

Ниже приведен пример:

  • Строка должна начинаться с ‘h’ и заканчиваться ‘o’ (например, привет, гало).
  • Строка может быть заключена в скобки.

2. Разработать план

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

  • Какие типы символов допускаются (слово, цифра, новая строка, диапазон и т. Д.)?
  • Сколько раз должен появляться персонаж (один или несколько, один раз, …)?
  • Есть ли какие-то ограничения, которым нужно следовать (опционально, заглядывание / отставание, если-то-еще,…)?

3. Внедрить / Тестировать / Рефакторинг

Очень важно иметь среду тестирования в реальном времени для проверки и улучшения вашего регулярного выражения. Есть такие сайты, как regex101.com , regexr.com и debuggex.com, которые предоставляют одни из лучших сред.

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

  • Правильно ли определены классы символов для конкретного домена?
  • Должен ли я написать больше тестовых строк, чтобы охватить больше вариантов использования?
  • Можно ли найти и изолировать некоторые проблемы и протестировать их отдельно?
  • Должен ли я рефакторировать свое выражение с помощью подшаблона, групп, условий и т. Д., Чтобы сделать его меньше, понятнее и гибче?

Практические примеры

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

Подбор пароля

password match

Сценарий:

  • От 6 до 12 символов
  • Должна иметь хотя бы одну заглавную букву
  • Должна иметь хотя бы одну строчную букву
  • Должен иметь хотя бы одну цифру
  • Должен содержать другие символы

Шаблон:

^(?=.*[az])(?=.*[AZ])(?=.*\d).{6,12}$

Это выражение основано на нескольких положительных взглядах (?=(regex)) . Предварительный просмотр соответствует чему-то, за которым следует объявленное (regex) . Порядок условий не влияет на результат. Внешние выражения очень полезны, когда есть несколько условий.
Мы могли бы также использовать отрицательный прогноз (?!(regex)) чтобы исключить некоторые диапазоны символов. Например, я мог бы исключить % с помощью (?!.*#) .

Давайте объясним каждый шаблон вышеприведенного выражения:

  1. ^ устанавливает позицию в начале строки
  2. (?=.*[az]) положительный прогноз, утверждает, что регулярное выражение .*[az] может быть сопоставлено:
    • .* соответствует любому символу (кроме новой строки) от нуля до неограниченного времени
    • [az] соответствует одному символу в диапазоне между a и z (с учетом регистра)
  3. (?=.*[AZ]) положительный прогноз, утверждает, что регулярное выражение .*[AZ] может быть сопоставлено:
    • .* соответствует любому символу (кроме новой строки) от нуля до неограниченного времени
    • [AZ] соответствует одному символу между A и Z (с учетом регистра)
  4. (? =. * \ d) положительный прогноз, утверждает, что регулярное выражение *\d может быть сопоставлено:
    • .* соответствует любому символу (кроме новой строки) от нуля до неограниченного времени
    • \d соответствует цифре [0-9]
  5. .{6,12} соответствует любому символу (кроме новой строки) от 6 до 12 раз
  6. $ устанавливает позицию в конце строки

Соответствующий URL

URL match

Сценарий:

  • Должен начинаться с http или https или ftp а затем ://
  • Должен соответствовать действительному доменному имени
  • Может содержать спецификацию порта ( http://www.sitepoint.com:80 )
  • Может содержать цифры, буквы, точки, дефисы, косые черты, несколько раз

Шаблон:

^(http|https|ftp):[\/]{2}([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4})(:[0-9]+)?\/?([a-zA-Z0-9\-\._\?\,\'\/\\\+&%\$#\=~]*)

Первый сценарий довольно легко решить с помощью ^(http|https|ftp):[\/]{2} .
Чтобы соответствовать доменному имени, мы должны помнить, что для правильности оно может содержать только буквы, цифры, дефисы и точки. В моем примере я ограничил количество символов после знаков препинания от 2 до 4, но его можно расширить для новых доменов, таких как .rocks или .codes . Доменное имя соответствует ([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}) .

Необязательная спецификация порта соответствует простой (:[0-9]+)? ,

URL может содержать несколько косых черт и несколько символов, повторенных много раз (см. RFC3986 ), для этого используется диапазон символов в группе ([a-zA-Z0-9\-\._\?\,\'\/\\\+&%\$#\=~]*) .
Действительно полезно сопоставлять каждый важный элемент с помощью метода capture () , поскольку он будет возвращать только те совпадения, которые нам нужны. Помните, что некоторые символы должны быть экранированы с помощью \ .

Ниже каждый подшаблон объяснял:

  1. ^ устанавливает позицию в начале строки
  2. группа захвата (http|https|ftp) , захватывает http или https или ftp
  3. : экранированный символ, соответствует символу : буквально
  4. [\/]{2} соответствует ровно 2 раза экранированному символу /
  5. группа захвата ([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}) :
    • [a-zA-Z0-9\-\.]+ соответствует одному и неограниченному числу символов в диапазоне между a и z, A и Z, 0 и 9, символу - буквально и символу . в прямом смысле
    • \. соответствует персонажу . в прямом смысле
    • [a-zA-Z]{2,4} соответствует одному символу от 2 до 4 раз между a и z или A и Z (с учетом регистра)
  6. группа захвата (:[0-9]+)? :
    • квантификатор ? соответствует группе от нуля или более раз
    • : соответствует характеру : буквально
    • [0-9]+ соответствует одному символу от 0 до 9 один или несколько раз
  7. \/? соответствует символу / буквально ноль или один раз
  8. группа захвата ([a-zA-Z0-9\-\._\?\,\'\/\\\+&%\$#\=~]*) :
    • [a-zA-Z0-9\-\._\?\,\'\/\\\+&%\$#\=~]* соответствует нулю и неограниченному числу раз одного символа в диапазоне az, AZ, 0-9, символы: -._?,'/\+&%$#=~ .

Соответствие HTML TAG

HTML TAG match

Сценарий:

  • Начальный тег должен начинаться с < за которым следует один или несколько символов, и заканчиваться >
  • Конечный тег должен начинаться с </ за которым следует один или несколько символов, и заканчиваться >
  • Мы должны соответствовать контенту внутри элемента TAG

Шаблон:

<([\w]+).*>(.*?)<\/\1>

Сопоставить начальный тег и содержимое внутри довольно просто с помощью <([\w]+).*> И (.*?) , Но в приведенном выше примере я добавил полезную вещь: ссылку на группу захвата.
Каждая группа захвата, определенная круглыми скобками () может быть передана с использованием ее номера позиции (first)(second)(third) , что позволит проводить дальнейшие операции.
Выражение выше может быть объяснено как:

  • Начать с <
  • Захватить имя тега
  • Вслед за одним или несколькими символами
  • Захват содержимого внутри тега
  • Закрывающий тег должен быть </tag name captured before>

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

Давайте копнем немного глубже и объясним подшаблоны:

  1. < соответствует персонажу < буквально
  2. группа захвата ([\w]+) соответствует любому символу слова a-zA-Z0-9_ один или несколько раз
  3. .* соответствует любому символу (кроме новой строки) от нуля или более раз
  4. > соответствует персонажу > буквально
  5. группа захвата (.*?) , соответствует любому символу (кроме новой строки), ноль и более раз
  6. < соответствует символам < буквально
  7. \/ соответствует символу / буквально
  8. \1 соответствует тому же тексту, который соответствует первой группе захвата: ([\w]+)
  9. > соответствует персонажам > буквально

Соответствие дублированным словам

HTML TAG match

Сценарий:

  • Слова разделены пробелом
  • Мы должны соответствовать каждому дублированию, а также непоследовательным

Шаблон:

\b(\w+)\b(?=.*\1)

Это регулярное выражение кажется сложным, но использует некоторые концепции, показанные ранее.
Шаблон вводит понятие границ слов.

Граница слова \b основном проверяет позиции. Соответствует, когда за символом слова (т.е. abcDE ) следует символ, не являющийся словом (т. abcDE -~,! ).
Ниже вы можете найти несколько примеров использования слова border, чтобы сделать его более понятным:
— учитывая фразу, Regular expressions are awesome
— Шаблон \bare\b соответствует
— Шаблон \w{3}\b может совпадать с тремя последними буквами слов: lar, ion, are, ome

Выражение выше может быть объяснено как:

  • Соответствует каждому символу слова, за которым следует символ, не являющийся словом (в нашем случае пробел)
  • Проверьте, присутствует ли соответствующее слово или нет

Ниже вы найдете объяснение для каждого подшаблона:

  1. \b граница слова
  2. группа захвата ([\w]+) соответствует любому символу слова a-zA-Z0-9_
  3. \b граница слова
  4. (?=.*\1) положительный прогноз утверждает, что может быть сопоставлено следующее:
    • .* соответствует любому символу (кроме новой строки)
    • \1 совпадает с тем же текстом, что и первая группа захвата

Выражение будет иметь больше смысла, если мы вернем все совпадения вместо того, чтобы возвращать только первое. Смотрите PHP-функцию preg_match_all для получения дополнительной информации.

Последние мысли

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

Хороший сценарий проблемы может быть очень полезен и позволит вам начать думать о диапазоне символов, ограничениях, утверждениях, повторениях, необязательных значениях и т. Д. Если уделить больше внимания групповым захватам, совпадения будут полезны для дальнейшей обработки. Не стесняйтесь улучшать выражения в примерах, и дайте нам знать, как вы делаете!

Полезные ресурсы

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

Lea Verou — / Reg (exp) {2} lained /: Демистификация регулярных выражений

https://www.youtube.com/watch?v=EkluES9Rvak

Библиотеки PHP

имя Описание
RegExpBuilder Создает регулярные выражения, используя понятные человеку цепочки методов
NooNooFluentRegex Создает выражения Regex, используя беглые сеттеры и английские термины, как указано выше.
Хоа \ Regex Предоставляет инструменты для анализа регулярных выражений и генерации строк
Regex реверс Учитывая регулярное выражение будет генерировать строку

Веб-сайты

URL Описание
regex101.com PCRE онлайн тестер регулярных выражений
regextester.com PCRE онлайн тестер регулярных выражений
rexv.org PCRE онлайн тестер регулярных выражений
debuggex.com Поддерживает PCRE и предоставляет очень полезный визуальный отладчик регулярных выражений
regexper.com Регулярное выражение стиля Javascript, но полезно для отладки
phpliveregex.com Онлайн тестер для функций preg
regxlib.com База данных регулярных выражений готова к использованию
regular-expressions.info Regex учебники, обзор книг, примеры

книги

заглавие Описание автор редактор
Освоение регулярных выражений Должен иметь книгу регулярных выражений Джеффри Фридл O’Reilly
Карманный справочник регулярных выражений Регулярные выражения для Perl, Ruby, PHP, Python, C, Java и .NET Тони Стаблбайн O’Reilly