Регулярные выражения PHP

Регулярные выражения PHP

Регулярные выражения в PHP (с англ. RegEx или regex) представляют собой последовательность символов, описывающих специальные шаблоны, которые применяются для различных вариантов обработки текста: проверки, поиска и замены того или иного фрагмента, состоящего из букв, цифр или любых других символов, в том числе специальных символов и символов пунктуации.

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

$exp = "/wm-school/i";

В приведенном выше примере, в качестве символа разделителя используется слэш /wm-school — это шаблон, по которому идет поиск, а символ i, расположенный после второго разделителя — это модификатор, позволяющий вести поиск без учета регистра.

В качестве символа разделителя может быть любой символ, кроме буквы, цифры, обратной косой черты \ или пробела. Самый распространенный разделитель — это слэш /, но если ваш шаблон содержит слэш, удобно выбрать другие разделители, такие как # или ~.

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

ФункцияОпределение
preg_match()Эта функция ищет конкретный образец в некоторой строке. Он возвращает 1 (true), если шаблон существует, и 0 (false) в противном случае.
preg_match_all()Эта функция ищет все вхождения шаблона в строке. Она возвращает количество найденных совпадений с шаблоном в строке, или 0 — если вхождений нет. Функция удобна для поиска и замены.
ereg_replace()Эта функция ищет определенный шаблон строки и возвращает новую строку, в которой совпадающие шаблоны были заменены другой строкой.
eregi_replace()Функция ведет себя как ereg_replace() при условии, что поиск шаблона не чувствителен к регистру.
preg_replace()Эта функция ведет себя как функция ereg_replace() при условии, что регулярные выражения могут использоваться как в шаблоне так и в строках замены.
preg_split()Функция ведет себя как функция PHP split(). Он разбивает строку на регулярные выражения в качестве параметров.
preg_grep()Эта функция ищет все элементы, которые соответствуют шаблону регулярного выражения, и возвращает выходной массив.
preg_quote()Эта функция принимает строку и кавычки перед каждым символом, который соответствует регулярному выражению.
ereg()Эта функция ищет строку, заданную шаблоном, и возвращает TRUE, если она найдена, иначе возвращает FALSE.
eregi()Эта функция ведет себя как функция ereg() при условии, что поиск не чувствителен к регистру.

Примечание:

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

Функция preg_match()

Функция preg_match() выполняет проверку на соответствие регулярному выражению.

Пример. Поиск подстроки «php» в строке без учета регистра:

<?php
$str = "PHP - это язык веб-сценариев.";
$pattern = "/php/i";
if (preg_match($pattern, $str)) {
  echo "Вхождение найдено.";
} else {
  echo "Вхождение не найдено.";
}

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

Примечание: Не используйте функцию preg_match(), если необходимо проверить наличие подстроки в заданной строке. Для этого используйте strpos() или strstr(), т.к. они выполнят эту задачу гораздо быстрее.

Функция preg_match_all()

Функция preg_match_all() выполняет глобальный поиск шаблона в строке.

В примере регулярное выражение используется для подсчета числа вхождений «ain» в строку без учета регистра:

<?php
$str = "The rain in England falls mainly on the plains.";
$pattern = "/ain/i";
echo preg_match_all($pattern, $str);
?>

Функция preg_replace()

Функция preg_replace() выполняет поиск и замену по регулярному выражению.

В следующем функция выполняет поиск в строке совпадений с шаблоном pattern и заменяет их на replacement:

<?php
$string = "Выпускной вечер в 2021 г";
$pattern = "/2021/i";
$replacement = "2022";
echo preg_replace($pattern, $replacement, $string);
?>

Модификаторы указываются либо в скобках, например так: (?Ui), либо после закрывающего символа ‘/pattern/Ui’.

МодификаторОписание
iВыполняет поиск без учета регистра. Например «/a/i» ищет и a, и A.
mВыполняет многострочный поиск (шаблоны, которые ищут начало или конец строки, будут соответствовать началу или концу каждой строки)
uОбеспечивает правильное сопоставление шаблонов в кодировке UTF-8 (для поиска русского текста например).
UИнвертирует «жадность» (по умолчанию жадный, т.е. пытается захватить как можно большую строку, подходящую по условию).
sЕсли используется, то символ точка (.) соответствует и переводу строки. Иначе она ему не соответствует.
xИгнорировать пробелы. В этом случае пробелы нужно экранировать обратным слэшем \.

При использовании модификаторов, можно использовать знак минус (-) для отключения модификатора. Например: (?m-i) — включаем многострочный поиск и отключаем регистронезависимый.

Квадратные скобки [b-d0-4xyz] означают, что нужно выбрать «один из этих символов», в данном случае — буквы bcdxyz или цифра от 0 до 4. Внутри квадратных скобок () не работают другие спецсимволы например | или * — они обозначают обычный символ. Если в квадратных скобках в начале стоит символ ^ то смысл меняется на противоположный: «любой один символ, кроме указанных» например, [^b-d] значит «один любой символ, кроме bc или d».

Квадратные скобки ([]) используются для нахождения ряда символов:

ВыражениеОписание
[abc]Один из символов a, b, c
[^abc]Любой символ кроме a, b, c
[0-9]Любой символ из диапазона от 0 до 9
[a-zА-Я]Любой символ из диапазонов

Примечание: в квадратных скобках можно указывать диапазоны символов, но следует помнить, что русская буква ё идет отдельно от алфавита и для создания регулярки «любая русская буква» нужно писать [а-яё].

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

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

Одним из основных метасимволов является обратный слэш (\), который меняет тип символа, следующего за ним, на противоположный. Таким образом обычный символ можно превратить в метасимвол, а если это был метасимвол, то он теряет свое специальное значение и становится обычным символом. Этот приём нужен для того, чтобы вставлять в текст специальные символы как обычные. Например, символ d в обычном режиме не имеет никаких специальных значений, но \d — это уже метасимвол, который обозначает: «любая цифра». Символ точка (.) в обычном режиме значит — «любой единичный символ», а экранированная точка (\.) означает просто точку.

В регулярных выражениях совпадения с набором обеспечивается с помощью метасимволов — квадратных скобочек [ ]. Любые два символа ASII могут быть указаны в качестве начала и конца диапазона. Для простой реализации, положим, мы хотим найти все пронумерованные файлы от 0 до 9 с расширением .jpg.


Регулярное выражение: [0-9]\.jpg

Результат: 1.jpg2.jpg3.jpg, photo.jpg, anime.jpg, 8.jpg, jkl.jpg

Стоит отметить, что имя файлов из более 1 цифры наше регулярное выражение не охватит. Про множественный выбор будет чуть ниже, а пока представим, что нам вдруг понадобилось добиться обратного результата. Добавим метасимвол ^ (у которого, самое противное, в регулярных выражениях есть аж две функции). Чтобы воспользоваться им как исключением, нужно добавить его именно внутрь нашего набора:

Регулярное выражение: [^0-9]\.jpg

Текст: 1.jpg, 2.jpg, 3.jpg, photo.jpg , anime.jpg , 8.jpg, jkl.jpg


МетасимволОписаниепример
.Соответствует любому одиночному символу, кроме новой строки././ соответствует строке, состоящей из одного символа.
^Соответствует началу строки./^cars/ соответствует любой строке, которая начинается с cars.
$Соответствует шаблону в конце строки./com$/ соответствует строке, заканчивающейся на com, например gmail.com
*Соответствует 0 или более вхождений./com*/ соответствует commute, computer, compromise и т.д.
+Соответствующий предыдущему символу появляется как минимум один раз.Например, /z+oom/ соответствует zoom.
\Используется для удаления метасимволов в регулярном выражении./google\.com/ будет рассматривать точку как буквальное значение, а не как метасимвол.
a-zСоответствует строчным буквам.cars
A-ZСоответствует буквам в верхнем регистре.CARS
0-9Соответствует любому числу от 0 до 9./0-5/ соответствует 0, 1, 2, 3, 4, 5
[…]Соответствует классу символов./[pqr]/ соответствует pqr
|Разделяет перечисление альтернативных вариантов./(cat|dog|fish)/ соответствует cat или dog или fish
\dЛюбая цифра./(\d)/ соответствует цифре
\sНайти пробельный символ (в т.ч. табуляция)./(\s)/ соответствует пробелу
\bГраница слова (начало или конец)./\bWORD/ найти совпадение в начале слова

Таблица пробельных метасимволов

[\b]возврат на один символ
\fперевод страницы
\nперевод строки
\rвозрат каретки
\tтабуляция
\vвертикальная табуляция

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

Повторения символов или комбинаций описываются с помощью квантификаторов (метасимволов, которые задают количественные отношения). Есть два типа квантификаторов: общие (задаются с помощью фигурных скобок {}) и сокращенные (сокращения наиболее распространенных квантификаторов). Фигурные скобки x{1,7} задают число повторений предыдущего символа (в этом случае выражение ищет от 1 до 7 идущих подряд букв «x»).

КвантификаторОписанте
a+Один и более раз a
a*Ноль и более раз a
a?Одна a или пусто
a{3}3 раза a
a{3,5}От 3 до 5 раз a
a{3,}3 и более раз a

Примечание: Если в выражении требуется поиск одного из метасимволов, вы можете использовать обратный слэш (\). Например, для поиска одного или нескольких вопросительных знаков (?) можно использовать следующее выражение: $pattern = '/\?+/';

Группы (подмаски) в регулярных выражениях делаются с помощью метасимвола группировки ().

Например в выражении xyz+ знак плюс (+) относится только к букве z и это выражение ищет слова типа xyzxyzzxyzzz. Но если поставить скобки x(yz)+ то квантифиактор (+) относится уже к последовательности yz и регулярка ищет слова xyzxyzyzxyzyzyz.

<?php
$str = "Hello, boy Bananan!";
$pattern = "/Ba(na){2}n/";
echo preg_match($pattern, $str);
?>

Ещё примеры:

ВыражениеОписание
^[a-zA-Z0-9_]{1,}$Любое слово, хотя бы одна буква, число или _
+@[a-z0-9A-Z]Соответствует строке с символом @ в начале, за которым следует любая буква нижнего регистра, число от 0 до 9 или буква верхнего регистра.
([wx])([yz])wy, wz, xy, или xz
[a-z]+Один или более символов нижнего регистра

Множественный выбор: делаем простую валидацию

Вооружившись полученными знаниями, попробуем сделать регулярное выражение, которое находит, например, слова короче 3 букв (стандартная задача для антиспама). Если мы попробуем использовать следующее регулярное выражение — \w{1,3} (в котором метасимвол \w указывает на любой символ, а фигурные скобки обозначают количество символов от сколько до скольки, то у нас выделятся все символы подряд — нужно как-то обозначить начало и конец слов в тексте. Для этого нам потребуется метасимвол \b.

Регулярное выражение: \b\w{1,3}\b:

Текст: good word
not
egg

Неплохо! Теперь слова короче трех букв не смогут попадать в нашу базу данных. Посмотрим на валидацию почтового адреса:

Регулярное выражение: \w+@\w+\.\w+

Требования: в электронной почте в начале должен быть любой символ (цифры или буквы, ведь электронная почта, которая состоит только из цифр в начале, встречается довольно часто). Потом идет символ @, затем — сколько угодно символов, после чего экранированная точка (т.е. просто точка) и домен первого уровня.

Подробнее рассмотрим повторение символов

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

Регулярное выражение: [2-6]+

Текст: Here are come’s 89 different 234 digits 24 .

Еще примеры регулярных выражений

РегуляркаРезультат
[0-9]{4}Соответствует году, пример: 2010
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}Соответствует IP-адресу, например: 192.168.10.1.
([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}Соответствует доменному имени, например: www.yahoo.com

Давайте я приведу таблицу всех квантификаторов метасимволов:

*символы повторяются 0 и до бесконечности
+повторяются от 1 и до бесконечности
{n}повторяются точно n раз
{n,}от n и до бесконечности
{n1, n2}от n1 и до n2 раз точно
?0 или 1 символ, не больше

В применении квантификаторов нет ничего сложного. Кроме одного нюанса: жадные и ленивые квантификаторы. Приведем таблицу:

**?
++?
{n,}{n,}?

Ленивые квантификаторы отличаются от жадных тем, что они выхватывают минимальное, а не максимальное количество символов. Представим, что есть у нас задача найти все теги заголовков h1-h6 и их контент, а весь остальной текст не должен быть затронут (я умышленно ввел несуществующий тэг h7, чтобы не мучаться с экранированием хабровских тэгов):

Регулярное выражение: <h[1-7]>.*?<\/h[1-7]>

Текст: <h7> hello </h7> lorem ipsum avada kedavra <h7> buy</h7>

Все сработало успешно, однако только благодаря ленивому квантификатору. В случае применения жадного квантификатора у нас выделился бы весь текст между тегами (полагаю, в иллюстрации это не нуждается).

Полезные ссылки и сервисы

https://regex101.com/ — сервис для написания и проверки регулярок

https://www.regexpal.com/ — еще один сервис для проверки регулярных выражений

https://htaccess.madewithlove.com/ — и еще один аналогичный сервис

https://rubular.com/ — еще один сервис для проверки со шпаргалками (Eng)

https://chrome.google.com/webstore/detail/regexp-tester/fekbbmalpajhfifodaakkfeodkpigjbk — приложение Google Chrome для проверки регулярок

Опубликовал(а)Teh
Предыдущая запись
Зачем нужны редиректы в SEO?
Добавить комментарий
Ваш электронный адрес не будет опубликован. Обязательные поля помечены *