W3docs

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 (группировка результатов по вхождению)

Такая структура наиболее удобна для перебора в цикле, когда у каждого совпадения есть несколько групп захвата:

php— editable, runs on the server

Вывод:

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() для разбиения строк по шаблону.

Практика

Практика
Какова цель функции preg_match_all() в PHP?
Какова цель функции preg_match_all() в PHP?
Was this page helpful?