2010-02-05 2 views
8

У меня есть строка, которая может выглядеть примерно так:PHP регулярных выражений - Повторяя матч из группы

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

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

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

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

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

ответ

5

Try:

<?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" 
} 

EDIT:

Поскольку вы хотите включить строку «Поданный под» в поисках, чтобы однозначно идентифицировать матч, вы можете попробовать это, я не уверен, если это может быть сделано с помощью одного вызова 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]); 
    } 
} 
+0

Спасибо, но мне действительно нужно использовать флаг «Подано под:». Хотя мой примерный текст был рудиментарным, фактический файл, который я обрабатываю, довольно сложный, и Filed under: действительно единственный уникальный идентификатор, с которым я должен работать. К счастью, он находится в конце файла, поэтому я могу полностью соответствовать цели. –

+0

достаточно близко. :) Благодаря. –

1

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

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

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

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

+0

Правильно, я попробовал только с квантором +. Это также терпит неудачу. И я тоже подумал о [запятой], о которой я боюсь, я не знаю, как это установить, поскольку второй или третий матч может иметь или не иметь запятую. Однако я попытался сделать это как мой attemp: [code] preg_match_all ("/ Filed under: (?: ([\ w | \ d | \ s] +?) <\/a>. *?) + /", $ R , $ match); [/ code] –

+0

Хммм, комментарии не очень красивые. –

+0

@Senica: вы можете использовать обратные ссылки для форматирования кода в комментариях так же, как вы можете в вопросах и ответах, но если код длинный или сложный, вы должны отредактировать свой вопрос и поместить его туда. Код, который вы указали выше, немного для комментария. –

2
$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 
+1

Иногда RegExes действительно лучший способ сделать что-то .... – SoapBox

+1

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

+0

Как я уже говорил в комментарии выше, я не могу использовать explode .... Во-первых, есть случаи, когда нет запятой, и есть только одна группа. Два, хотя мой пример был прост, это сложный файл. Тег не так прост. В-третьих, мне нужно, чтобы Filed at: attribute, поскольку использование взрыва наверняка вернет нежелательные значения. –

8

Просто для удовольствия вот регулярное выражение, которое будет работать с одним 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 reference
\G reference

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

+0

Я не знал о '\ K'. Интересно! Небольшое примечание о '\ G' - вы ссылаетесь на« предыдущий матч », который в порядке, и на« следующее совпадение », что немного запутывает (особенно, когда пример Perl, с которым вы связаны, прямо вводит в заблуждение - он * устанавливает * следующую позицию в коде - **, которая сильно отличается от поведения по умолчанию **). Проще говоря - '\ G' относится к позиции, в которой было начато текущее совпадение. Оно также неточно' 'всегда будет соответствовать после' Filed under: '- оно также может совпадать в начале строки, для пример ', Group2': http://ideone.com/aTjrm. – Kobi

+0

(кстати, я пришел отсюда: http://stackoverflow.com/questions/5982451/regex-capturing-a-repeated-group/7135730#7135730) – Kobi

+0

Хм, на самом деле, мое определение '\ G' является тоже нехорошо. – Kobi

Смежные вопросы