preg_match_all()
Функция preg_match_all() в PHP выполняет глобальный поиск по регулярному выражению и возвращает все найденные совпадения в строке.
Введение
В PHP регулярные выражения незаменимы для поиска и обработки строк. Тогда как preg_match() останавливается на первом совпадении, preg_match_all() продолжает сканирование и возвращает все вхождения шаблона в строке. Используйте её, когда нужно извлечь все номера телефонов, все теги, все слова или любую повторяющуюся структуру из текста.
В этой статье описаны синтаксис, важный аргумент $flags, управляющий структурой результатов, и несколько практических примеров.
Синтаксис
preg_match_all(
string $pattern,
string $subject,
array &$matches = null,
int $flags = PREG_PATTERN_ORDER,
int $offset = 0
): int|false$pattern— регулярное выражение, ограниченное разделителями/.../(или любыми другими парными разделителями).$subject— строка для поиска.$matches— выходной массив (передаётся по ссылке), заполняемый всеми найденными совпадениями.$flags— необязательный. Управляет структурой$matches(см. ниже).$offset— необязательный. Байтовое смещение в$subject, с которого начинается поиск.
Функция возвращает количество полных совпадений шаблона (которое может быть 0), либо false, если шаблон недействителен.
Простой поиск
Наиболее простой сценарий — собрать все подстроки, соответствующие шаблону. Здесь мы извлекаем все числа из предложения:
<?php
$subject = 'Room 12, floor 3, building 7';
$count = preg_match_all('/\d+/', $subject, $matches);
echo "Found $count numbers\n";
print_r($matches[0]);Вывод:
Found 3 numbers
Array
(
[0] => 12
[1] => 3
[2] => 7
)Если в шаблоне нет групп захвата, $matches[0] содержит список полных совпадений.
Выбор флага: PREG_PATTERN_ORDER или PREG_SET_ORDER
Аргумент $flags определяет, как организованы совпадения и группы захвата. Два основных флага являются взаимоисключающими:
PREG_PATTERN_ORDER(по умолчанию) —$matches[0]содержит все полные совпадения,$matches[1]— все захваты группы 1,$matches[2]— все захваты группы 2 и т. д. Думайте об этом как «столбец за столбцом».PREG_SET_ORDER—$matches[0]представляет первое полное совпадение (полное совпадение + его группы),$matches[1]— второе и т. д. Думайте об этом как «строка за строкой».
Также можно добавить PREG_OFFSET_CAPTURE, чтобы вместе с текстом записывать байтовое смещение каждого совпадения.
PREG_SET_ORDER (группировка результатов по вхождению)
Такая структура наиболее удобна для перебора в цикле, когда у каждого совпадения есть несколько групп захвата:
Вывод:
Name: Alice, Age: 25
Name: Bob, Age: 30При использовании PREG_SET_ORDER каждый $match — это одно вхождение: $match[0] — полное совпадение, $match[1] — первая группа (имя), $match[2] — вторая группа (возраст).
PREG_PATTERN_ORDER (группировка результатов по шаблону)
Тот же шаблон с флагом по умолчанию возвращает группы в виде параллельных массивов:
<?php
$pattern = '/([A-Z][a-z]+) (\d+)/';
$subject = 'Alice 25 Bob 30';
preg_match_all($pattern, $subject, $matches, PREG_PATTERN_ORDER);
print_r($matches[1]); // all names
print_r($matches[2]); // all agesВывод:
Array
(
[0] => Alice
[1] => Bob
)
Array
(
[0] => 25
[1] => 30
)Именованные группы захвата
Именование групп с помощью (?<name>...) делает результат самодокументированным — имена становятся ключами массива (наряду с числовыми индексами):
<?php
$pattern = '/(?<name>[A-Z][a-z]+) (?<age>\d+)/';
$subject = 'Alice 25 Bob 30';
preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
echo "{$match['name']} is {$match['age']}\n";
}Вывод:
Alice is 25
Bob is 30Распространённые ошибки
- Проверяйте возвращаемое значение, а не массив. Шаблон может совпасть ноль раз и при этом выполниться успешно;
preg_match_all()вернёт0, тогда какfalseозначает, что само регулярное выражение недействительно. Используйте=== falseдля обнаружения ошибок. Подробную причину сбоя можно узнать с помощьюpreg_last_error(). $matchesперезаписывается. Каждый вызов заменяет предыдущее содержимое выходного массива.- Выбирайте правильный флаг для вашего цикла. Используйте
PREG_SET_ORDER, если хотите одну строку на каждое совпадение; используйтеPREG_PATTERN_ORDERпо умолчанию, если хотите один столбец на каждую группу. - Экранируйте специальные символы в динамических шаблонах с помощью
preg_quote(), если шаблон поступает из пользовательского ввода.
Заключение
preg_match_all() возвращает все совпадения шаблона в строке, что делает её основной функцией для извлечения повторяющихся данных. Ключ к правильному использованию — понимание аргумента $flags: PREG_SET_ORDER группирует результаты по вхождению, а PREG_PATTERN_ORDER по умолчанию — по группе захвата.
Для смежных задач смотрите preg_match() для поиска одного совпадения, preg_replace() для поиска с заменой и preg_split() для разбиения строк по шаблону.