Dr_Death
@Dr_Death

Как заставить preg_match_all возвращать действительно все вхождения?

Есть например:
$string = ' 1 2 3 4 5 6 ';
preg_match_all('/ \d+ \d+ /', $string, $matches);


вернет:
array(
   0 => ' 1 2 ',
   1 => ' 4 5 ',
);


А хочу чтоб вернул все варианты:
array(
    0 => ' 1 2 ',
    1 => ' 2 3 ',
    2 => ' 3 4 ',
    3 => ' 4 5 ',
    4 => ' 5 6 ',
);


Толи лыжи не едут, толи я
  • Вопрос задан
  • 7618 просмотров
Пригласить эксперта
Ответы на вопрос 7
utf
@utf
(?=( \d+ \d+ )) Только оно возвращает еще и массив с пустыми строками и регулярка будет медленно работать с большими строками — типо O(count($string))
Ответ написан
Комментировать
Anonym
@Anonym
Программирую немного )
Ищет в строке subject все совпадения с шаблоном pattern и помещает результат в массив matches в порядке, определяемом комбинацией флагов flags.

После нахождения первого соответствия последующие поиски будут осуществляться не с начала строки, а от конца последнего найденного вхождения.

php.net

Так что, видимо, нельзя.
Ответ написан
@boodda
вот это реально не юзабельный и не читабельный велосипед, чуть данные поменялись и все придётся менять.
Готов предложить конкретно под вас более быстрый и более вменяемый велосипед)

$s = ' 1 2 3 4 5 6 7 8 9 10 11 12 ';
$matches = array();
$exp = preg_split('#\s+#u', trim($s));
foreach($exp as $key => $piece){
    if(isset($exp[$key - 1])) $matches[] = $exp[$key - 1].' '.$piece;
}
var_dump($matches);
Ответ написан
Wott
@Wott
попробуйте позитивный просмотр вперед сразу после первой цифры
Ответ написан
Комментировать
@boodda
На этой неделе решал точно такую же задачу.
Адаптировано вашей задаче будет выглядеть так:

$string = ' 1 2 3 4 5 6 ';
$out = array();
while(preg_match('/ \d+ \d+ /', $string, $matches, PREG_OFFSET_CAPTURE)){
    $out[] = $matches[0];
    $string = substr($string, $matches[0][1] + 1);
}
var_dump($out);


Насколько медленно не знаю, не тестил у меня не большой объём данных.
Ответ написан
@boodda
последний вариант очень быстро) быстрее preg_match явно, а какие 3 символа?
разделители? или имеется ввиду что по 3 надо тоже все найти?
Ответ написан
alekciy
@alekciy
Вёбных дел мастер
То ли лыжи не едут, то ли я

Регулярка вернула ровно то, что от неё просили.

1) Позиция 0: выражение '/ \d+ \d+ /' для строки ' 1 2 3 4 5 6 ' матчится в ' 1 2 ' и текущей позицией становится 5.
2) Позиция 5: выражение '/ \d+ \d+ /' для строки '3 4 5 6 ' не матчится, текущей позицией становится 6 (относительно исходной строки конечно).
3) Позиция 6: выражение '/ \d+ \d+ /' для строки ' 4 5 6 ' матчится в ' 4 5 ' и текущей позицией становится 11.
4) Позиция 11: выражение '/ \d+ \d+ /' для строки '6 ' не матчится как и все последующие до конца строки.

Результат: ' 1 2 ' и ' 4 5 '.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы