PHP正则表达式 - 重复匹配组

时间:2010-02-05 03:56:02

标签: php regex

我有一个字符串可能看起来像这样:

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

这是我目前使用的正则表达式:

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

我希望正则表达式在()内继续进行最后指定的+?匹配。但它不会这样做。 ::叹息::

任何想法。我知道必须有一种方法可以在一个正则表达式中执行此操作,而不是将其分解。

4 个答案:

答案 0 :(得分:9)

只是为了好玩,这里的正则表达式适用于单个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>标记之后开始(它就像一个积极的外观,但更灵活)。最后,[^<>]+会匹配代码的内容,并将匹配位置添加到结束代码,以便\G可以匹配。

但是,正如我所说,这只是为了好玩。如果你没有 在一个正则表达式中完成这项工作,你最好采用多步骤方法,如使用的@codaddict;它更具可读性,更灵活,更易于维护。

\K reference
\G reference

编辑:虽然我给出的引用是针对Perl文档的,但PHP也支持这些功能 - 或者更准确地说,是PCRE lib。我认为Perl文档好一点,但您也可以在PCRE manual中阅读这些内容。

答案 1 :(得分:7)

尝试:

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

修改

由于您希望在搜索中包含字符串'Filed under'以唯一标识匹配,您可以尝试这一点,我不确定是否可以使用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]); 
    }
}

答案 2 :(得分: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

答案 3 :(得分:1)

  

我希望正则表达式在()内部继续使用+指定匹配?最后。

+?是一个懒惰的量词 - 它会尽可能少地匹配。换句话说,只需一次。

如果你想多次匹配,你需要一个贪婪的量词 - +

另请注意,正则表达式不能正常工作 - 匹配会在遇到标记之间的逗号后立即失败,因为您没有考虑到它。这可能需要纠正。