PHP, Регулярные выражения: достать все попадающие под условия подстроки
Есть строка, которая содержит группу номеров. Количество групп заранее неизвестно, но не менее одной. Известно, что номера вводятся строго через пробел и каждый номер состоит строго из 4 цифр. Необходимо составить такое регулярное выражение, которое бы доставало все номера из строки. При этом в случае когда один из номеров не соответствует формату, регулярка отрабатывать не должна.
Пример 1:
строка:
1111 2222 3333 4444 5555 6666
ожидаемый результат:
["1111", "2222", "3333", "4444", "5555", "6666"]
Пример 2:
строка:
1111 222 3333
ожидаемый результат:
[]
Я пытался делать через preg_match_all() с таким выражением: /\A(\d\d\d\d\s?)+\z/. Оно отрабатывает на всю строку, но достает только последний номер. То есть из первого примера я получаю только 4444. В чем моя ошибка?
Ответы (2 шт):
А так:
^(\d{4} )*?\d{4}$
^ - начало строки
(\d{4} )*? - начинается с произвольного количества групп "1234_"
$ - конец строки
\d{4}$ - заканчивается на одну группу из 4-х цифр
preg_match_all('/^(\d{4} )*?\d{4}$/', '1234 5678 5668', $matches);
print_r(json_encode(explode(' ', $matches[0][0])));
Используйте двухэтапный подход: валидируйте строку с помощью вашего регулярного выражения и preg_match, а потом разбейте строку (если валидна) по пробелам:
$str = "1111 2222 3333 4444 5555 6666";
if (preg_match('~\A(?:\d{4}\s?)+\z~', $str)) {
// if (preg_match('~\A\d{4}(?:\s\d{4})*\z~', $str)) { // или так, если в конце не должно быть пробельных символов
print_r(preg_split('~\s~', $str));
// print_r(explode(' ', $str)); // если пробелы обычные
}
См. пример работы кода.
Можно, конечно, придумать нечто экзотическое и объединить валидацию и извлечение в один preg_match_all:
$str = "1111 2222 3333 4444 5555 6666";
if (preg_match_all('~(?:\G(?!\A)\s?|\A(?=(?:\d{4}\s?)+\z))(\d{4})~', $str, $m)) {
print_r($m[1]);
}
См. пример работы кода. Однако очень мало кто разберёт, что здесь к чему.
(?:\G(?!\A)\s?|\A(?=(?:\d{4}\s?)+\z))- одно из двух:\G(?!\A)\s?- конец предыдущего совпадения и опциональный пробельный символ|- или\A(?=(?:\d{4}\s?)+\z)- начало строки, сразу после которого должны следовать 1 и более последовательностей из четырёх цифр и одного необязательного пробельного символа до конца строки
(\d{4})- Захватывающая подмаска №1: четыре цифры.