Регулярное выражение PHP – повторение соответствия группы

У меня есть строка, которая может выглядеть примерно так:

$r = 'Filed under: <a>Group1</a>, <a>Group2</a>'; 

Вот регулярное выражение, которое я использую до сих пор:

 preg_match_all("/Filed under: (?:<a.*?>([\w|\d|\s]+?)<\/a>)+?/", $r, $matches); 

Я хочу, чтобы регулярное выражение внутри () продолжало делать совпадения в соответствии с символом +? в конце. Но это просто не будет. ::вздох::

Есть идеи. Я знаю, что должен быть способ сделать это в одном регулярном выражении, а не разбивать его.

Пытаться:

 <?php $r = 'Filed under: <a>Group1</a>, <a>Group2</a>, <a>Group3</a>, <a>Group4</a>'; if(preg_match_all("/<a.*?>([^<]*?)<\/a>/", $r, $matches)) { var_dump($matches[1]); } ?> 

вывод:

 array(4) { [0]=> string(6) "Group1" [1]=> string(6) "Group2" [2]=> string(6) "Group3" [3]=> string(6) "Group4" } 

РЕДАКТИРОВАТЬ:

Поскольку вы хотите включить строку «Подано в» в поиске, чтобы однозначно идентифицировать совпадение, вы можете попробовать это, я не уверен, что это можно сделать, используя один вызов preg_match

 // Since you want to match everything after 'Filed under' if(preg_match("/Filed under:(.*)$/", $r, $matches)) { if(preg_match_all("/<a.*?>([^<]*?)<\/a>/", $matches[1], $matches)) { var_dump($matches[1]); } } 

Просто для удовольствия это регулярное выражение, которое будет работать с одним preg_match_all :

 '%(?:Filed under:\s*+|\G</a>)[^<>]*+<a[^<>]*+>\K[^<>]*%` 

Или, в более читаемом формате:

 '%(?: Filed under: # your sentinel string | \G # NEXT MATCH POSITION </a> # an end tag ) [^<>]*+ # some non-tag stuff <a[^<>]*+> # an opening tag \K # RESET MATCH START [^<>]+ # the tag's contents %x' 

\G соответствует позиции, в которой начнется следующая попытка совпадения, которая обычно является местом, где закончилось предыдущее успешное совпадение (но если предыдущее совпадение было нулевой длины, оно снова продвигалось вперед). Это означает, что регулярное выражение не будет соответствовать подстроке, начиная с </a> до тех пор, пока оно не будет совпадать с начальным с Filed under: по крайней мере один раз.

После того, как цепочка дозорного или конечного тега была сопоставлена, [^<>]*+<a[^<>]*+> потребляет все до и включая следующий стартовый тег. Затем \K подталкивает начальную позицию, так что совпадение (если оно есть) появляется после тега <a> (это похоже на положительный lookbehind, но более гибкий). Наконец, [^<>]+ соответствует содержимому тега и добавляет позицию соответствия до конца, чтобы \G мог совпадать.

Но, как я уже сказал, это просто весело. Если вам не нужно выполнять задание в одном регулярном выражении, вам будет лучше с многоступенчатым подходом, например, с одним используемым @codaddict; это более читаемый, более гибкий и более удобный.

\K ссылка
Ссылка \G

EDIT: Хотя ссылки, которые я дал для документов Perl, эти функции также поддерживаются PHP, или, точнее, с помощью PCRE lib. Я думаю, что документы Perl немного лучше, но вы также можете прочитать об этом в руководстве PCRE .

 $r = 'Filed under: <a>Group1</a>, <a>Group2</a>' $s = explode("</a>",$r); foreach ($s as $k){ if ($k){ $k=explode("<a>",$k); print "$k[1]\n"; } } 

вывод

 $ php test.php Group1 Group2 

Я хочу, чтобы регулярное выражение внутри () продолжало делать совпадения в соответствии с символом +? в конце.

+? является ленивым квантором – он будет соответствовать как можно меньше времени. Другими словами, только один раз.

Если вы хотите совместить несколько раз, вам нужен жадный квантификатор – + .

Также обратите внимание, что ваше регулярное выражение не совсем работает – совпадение заканчивается, как только он встречает запятую между тегами, потому что вы ее не учли. Скорее всего, потребуется исправление.