Menu

PHP preg_match(): регулярные выражения с примерами

preg_match($pattern, $subject, $matches) проверяет строку по регулярному выражению и возвращает 1 при совпадении и 0, если совпадения нет. Группы захвата, именованные группы, preg_match_all, якоря, шаблоны для проверки и модификатор u для UTF-8, кириллицы и японского текста.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

preg_match($pattern, $subject, $matches) проверяет, совпадает ли строка с регулярным выражением. Функция возвращает 1 при совпадении и 0 в остальных случаях и заполняет $matches найденным: preg_match('/\d+/', 'Order 4521 shipped', $m) возвращает 1 и записывает в $m[0] значение "4521".

Шаблон это строка с разделителями вокруг, обычно /.../, за которыми идут модификаторы, например i. Пишите шаблоны в одинарных кавычках: внутри двойных PHP сначала раскрывает $name и escape-последовательности вроде \x41 или \101, и движок регулярных выражений может получить не тот шаблон, который вы набрали.

Группы захвата

Круглые скобки в шаблоне захватывают ту часть строки, с которой совпали. $m[0] это всё совпадение, $m[1] первая группа, $m[2] вторая, отсчёт ведётся по открывающим скобкам слева направо.

Именованные группы

(?<name>...) даёт группе имя. Значение хранится и под именем, и под номером, поэтому код, который читает результат, не сломается, если кто-то добавит группу раньше в шаблоне.

Все совпадения через preg_match_all

preg_match_all() продолжает поиск после первого совпадения и возвращает число совпадений. По умолчанию $m[0] содержит все полные совпадения, а $m[1] все значения первой группы. С PREG_SET_ORDER вы получаете по массиву на каждое совпадение, и по нему проще идти циклом.

Проверка ввода: якоря, номера телефонов, почтовые индексы

Для проверки шаблон должен совпадать со всей строкой, поэтому начинайте его с ^ и заканчивайте $. Одна ловушка: $ совпадает и перед последним переносом строки, поэтому '/^\d+$/' принимает "123\n". Добавьте модификатор D или используйте \z, который совпадает только в самом конце.

Регулярное выражение для адресов email либо отклоняет допустимые адреса, либо принимает недопустимые. Вместо него используйте filter_var($email, FILTER_VALIDATE_EMAIL) (смотрите filter_var()).

Модификатор u для UTF-8 и японского текста

Без модификатора u шаблон работает с байтами. Японский символ занимает в UTF-8 три байта, поэтому . совпадает с третью символа, и длины получаются неправильными. С u шаблон работает с символами, и можно использовать классы свойств Unicode.

u ещё и проверяет строку: если она не является корректным UTF-8, preg_match() возвращает false, а не ищет совпадение.

Экранирование пользовательского ввода через preg_quote

Символы вроде ., +, ?, ( и / имеют в шаблоне особый смысл. Если часть шаблона приходит из переменной, например поисковый запрос, пропустите её через preg_quote() с разделителем вторым аргументом, иначе 1+1 совпадёт с 11, а неэкранированный / сломает шаблон.

Неверный шаблон не выбрасывает исключение. PHP печатает предупреждение, а preg_match() возвращает false:

Warning: preg_match(): No ending delimiter '/' found in /path/to/index.php on line 3

Поэтому проверяйте === false (или preg_last_error_msg()), когда шаблон собирается во время выполнения. Для простой проверки подстроки без всякого шаблона str_contains() быстрее и понятнее. Чтобы изменить найденный текст, используйте preg_replace().

Часто задаваемые вопросы

Что возвращает preg_match в PHP?

1, если шаблон совпал, 0, если нет, и false, если сам шаблон неверен. Поскольку 0 и false оба ложны, сравнивайте через === 1, когда нужно отличить сломанный шаблон от отсутствия совпадения.

Как получить найденный текст из preg_match?

Передайте третий аргумент: preg_match('/(\d+)/', 'Order 4521', $m). Тогда $m[0] это всё совпадение, а $m[1] первая группа захвата, здесь обе равны "4521". С именованной группой (?<id>\d+) значение есть и в $m['id'].

Чем preg_match отличается от preg_match_all?

preg_match() останавливается на первом совпадении. preg_match_all() находит все совпадения, возвращает их количество и заполняет $matches всеми: preg_match_all('/\d+/', 'a1 b22 c333', $m) возвращает 3, а $m[0] равно ["1", "22", "333"].

Как использовать preg_match с кириллицей, японским или другим текстом в UTF-8?

Добавьте модификатор u: preg_match('/^.{3}$/u', '日本語') возвращает 1. Без u PHP работает со строкой как с байтами, поэтому . совпадает с одним байтом трёхбайтового символа. С u можно использовать и классы Unicode, например \p{Han}, \p{Hiragana} и \p{Katakana}.

Как проверить, что строка содержит только цифры, в PHP?

preg_match('/^\d+$/D', $s) или без регулярного выражения ctype_digit($s). Модификатор D (или \z вместо $) важен: обычный $ принимает и перенос строки в конце, поэтому "123\n" прошло бы проверку.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ