Регулярные выражения в PHP
Регулярные выражения в PHP: синтаксис паттернов, функции preg_, валидация, поиск и замена текста с примерами кода.
Регулярное выражение (regex) — это паттерн, описывающий набор строк. Вместо поиска одного фиксированного фрагмента текста вы описываете его форму — «адрес электронной почты», «последовательность цифр», «слово, заканчивающееся на .php» — и PHP находит, проверяет, заменяет или разбивает текст, соответствующий этому паттерну.
В этой главе рассматривается, как работают функции preg_ в PHP, синтаксис паттерна (разделители, классы символов, кванторы, группы, якоря), а также наиболее частые практические задачи: валидация ввода, извлечение данных и замена текста.
Что такое регулярные выражения
Регулярное выражение — это последовательность символов, определяющая паттерн поиска. Большинство символов совпадают сами с собой — паттерн cat совпадает с текстом cat. Мощь регулярных выражений заключается в метасимволах, обозначающих категории символов или повторение:
| Токен | Значение | Пример совпадения |
|---|---|---|
. | Любой одиночный символ (кроме новой строки) | c.t → cat, cut |
\d | Цифра 0-9 | \d\d → 42 |
\w | «Словесный» символ (a-z, A-Z, 0-9, _) | \w+ → hello_1 |
\s | Пробельный символ (пробел, табуляция, новая строка) | — |
[abc] | Любой из символов a, b, c | [aeiou] → e |
[^abc] | Любой символ кроме a, b, c | — |
a* | Ноль или более a | "", aaa |
a+ | Один или более a | a, aaa |
a? | Ноль или один a (необязательный) | "", a |
a{2,4} | От 2 до 4 символов a | aa, aaaa |
^ / $ | Начало / конец строки | — |
| | Альтернатива («или») | cat|dog → cat или dog |
() | Группировка / захват | (ab)+ → abab |
Как работают регулярные выражения в PHP
PHP использует PCRE (Perl-Compatible Regular Expressions) через семейство функций preg_. Наиболее часто используемые:
| Функция | Что делает |
|---|---|
preg_match() | Проверяет совпадение паттерна; захватывает первое совпадение |
preg_match_all() | Находит все совпадения в строке |
preg_replace() | Заменяет каждое совпадение новым текстом |
preg_split() | Разбивает строку по паттерну |
preg_quote() | Экранирует метасимволы regex в литеральной строке |
Синтаксис паттерна в PHP
Паттерн в PHP — это строка, состоящая из трёх частей: разделителя, паттерна и необязательных модификаторов.
/pattern/modifiersПервый символ — это разделитель — почти всегда /, но подойдёт любой неалфавитно-цифровой символ (#, ~, !). Выбор разделителя, который не встречается в вашем паттерне, избавляет от необходимости экранирования. Например, при совпадении URL-пути удобнее использовать #:
"#^/users/\d+$#" // no need to escape the slashesmodifiers — это необязательные буквы после закрывающего разделителя, изменяющие поведение движка:
i— без учёта регистра:/php/iсовпадает сPHP,Php,php.m— многострочный режим:^и$совпадают с началом/концом каждой строки, а не всей строки целиком.s— одинарная строка («dotall»):.также совпадает с символами новой строки.u— обрабатывать паттерн и строку как UTF-8. Используйте для любого текста с не-ASCII символами.x— расширенный режим: пробелы в паттерне игнорируются, что позволяет разбивать и комментировать сложные паттерны.
Проверка совпадения с помощью preg_match
preg_match() возвращает 1, если паттерн найден, 0 — если нет, и false при ошибке. Это правильный выбор для вопросов «да/нет», например: «содержит ли эта строка цифру?»
Необязательный третий аргумент $matches заполняется результатами: $matches[0] — это полное совпадение, а $matches[1], $matches[2], … — это захватывающие группы в порядке их появления — подстроки, захваченные каждой парой скобок.
Валидация пользовательского ввода
Одно из распространённых применений regex — валидация пользовательского ввода: проверка того, что значение имеет правильную форму, прежде чем его сохранить или использовать. Вот простая проверка электронной почты:
<?php
$email = "[email protected]";
if (preg_match("/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/", $email)) {
echo "Valid email address";
} else {
echo "Invalid email address";
}
?>Якоря ^ и $ здесь важны: без них паттерн совпадал бы с адресом электронной почты внутри более длинной строки, и "junk [email protected] junk" прошёл бы проверку. С якорями вся строка должна представлять собой единственный адрес электронной почты.
Для проверки email в частности встроенная функция PHP filter_var() с FILTER_VALIDATE_EMAIL надёжнее, чем написанный вручную regex. Обращайтесь к regex, когда вам нужен формат, который не поддерживают фильтры, — почтовые индексы, пользовательские идентификаторы, форматы телефонов. Полный пример проверки ввода см. в разделе Валидация форм в PHP.
Поиск всех совпадений с помощью preg_match_all
Там, где preg_match() останавливается на первом совпадении, preg_match_all() собирает все — это удобно для извлечения каждого хэштега, цены или ссылки из блока текста.
<?php
$text = "Prices: $12, $7 and $349";
preg_match_all("/\\\$(\d+)/", $text, $matches);
print_r($matches[1]); // the captured numbers
?>$matches[1] содержит массив всех захваченных групп — в данном случае ["12", "7", "349"].
Замена текста с помощью preg_replace
preg_replace() заменяет каждое совпадение. В строке замены $1, $2, … ссылаются на захваченные группы, поэтому вы можете не только удалять, но и переписывать:
<?php
$date = "2026-06-21";
// Reformat YYYY-MM-DD into DD/MM/YYYY
echo preg_replace("/(\d{4})-(\d{2})-(\d{2})/", "$3/$2/$1", $date);
// 21/06/2026
?>Чтобы разбить строку на части по паттерну вместо замены, используйте preg_split() — например, разбиение по любому количеству пробелов с помощью /\s+/.
Продвинутые техники
Освоив основы, вы сможете использовать следующие возможности для работы с более сложными паттернами:
- Захватывающие группы
(...)— извлекают конкретные части совпадения, как показано выше с$matches[1]. - Незахватывающие группы
(?:...)— группируют без занятия слота$matches, когда группировка нужна только для квантора или альтернативы. - Именованные группы
(?<year>\d{4})— ссылка на совпадение по имени ($matches['year']) вместо номера. - Предпросмотр вперёд
(?=...)и предпросмотр назад(?<=...)— совпадение на основе того, что идёт после или перед, без его потребления. Полезно для «числа, за которым следуетpx», без захватаpx. - Ленивые кванторы
*?,+?— совпадение с минимально возможным числом символов. По умолчанию.*является жадным и захватывает всё возможное.
Замечание об экранировании: символы вроде ., +, *, ?, (, ), [, \ имеют особое значение. Чтобы совпасть с ними буквально, добавьте обратный слэш (\. совпадает с буквальной точкой). Когда литеральный текст берётся из переменной, используйте preg_quote() для его безопасного экранирования.
Частые ошибки
- Забытые разделители. Паттерны в PHP являются строками и должны включать разделители:
"/\d+/", а не"\d+". Их отсутствие вызывает предупреждение, и совпадение не находится. - Двойное экранирование в строках с двойными кавычками. Внутри
"..."обратный слэш также является PHP-экранирующим символом."/\d/"работает, потому что\dне является PHP-последовательностью экранирования, но для совпадения с буквальным$нужно написать"/\\$/". Строки с одинарными кавычками ('/\d/') избавляют от этого сюрприза. - Жадное совпадение захватывает слишком много.
<.*>на<a><b>совпадает со всей строкой<a><b>, а не только с<a>. Используйте ленивое<.*?>или отрицательный класс<[^>]*>. - Пропуск модификатора
uдля UTF-8. Без/u.и\wработают на уровне байтов, искажая многобайтовые символы.
Заключение
Регулярные выражения позволяют описывать форму текста, а не его точное содержимое, что делает их незаменимыми для валидации ввода, извлечения данных и преобразования строк. В PHP для их использования применяются функции preg_: preg_match() и preg_match_all() для поиска, preg_replace() для перезаписи и preg_split() для разбивки строк. Начните с якорей, классов символов и кванторов, затем добавляйте группы и предпросмотр по мере усложнения паттернов. Чтобы узнать больше о строках, с которыми вы будете работать, см. PHP Строки.