如何使用PHP获取每个匹配的正则表达式模式

时间:2013-12-14 11:28:57

标签: php regex

我试图使用preg_match_all从html字符串中提取重复的模式。

问题似乎是我的模式有一个已定义的开头和结尾,但两者之间有一个通配符部分。因此,preg_match_all最终只能获得最大匹配,而不是单个匹配。

我的最终目标是将每个<a ...>some text</a>与html字符串隔离开来,然后将它们包装起来:<font ...><a ...>some text</a></font>

但首先我想简单地成功地将它们分开:

$lvs_regex = "/<a.+<\/a>/" ;
$lvs_test  = "click <a href='...'>AAA</a> now, <a href='...'>BBB</a> later, <a href='...'>CCC</a> tomorrow" ;

preg_match_all( $lvs_regex , $lvs_test , $matches ) ;
for($i = 0 ; $i < count( $matches ) ; $i++ )
  { print $matches[ $i ][0] . "<br/>" ;
  } 

我想要的回报:

[0] =&gt; <a href='...'>AAA</a>

[1] =&gt; <a href='...'>BBB</a>

[2] =&gt; <a href='...'>CCC</a>

但我只得到一场比赛:

[0] =&gt; <a href='...'>AAA</a> now, <a href='...'>BBB</a> later, <a href='...'>CCC</a>

2 个答案:

答案 0 :(得分:1)

也许是这样的:

$lvs_regex = "/<a.*?<\/a>/" ;
$lvs_test  = "click <a href='...'>AAA</a> now, <a href='...'>BBB</a> later, <a href='...'>CCC</a> tomorrow" ;

preg_match_all( $lvs_regex , $lvs_test , $matches);

基本上所需的模式是/<a.*?<\/a>/。这匹配在字符串中每次出现。

现在,var_dump($matches[0])给出了

array (size=3)
    0 => string '<a href='...'>AAA</a>' (length=21)
    1 => string '<a href='...'>BBB</a>' (length=21)
    2 => string '<a href='...'>CCC</a>' (length=21)

这是你想要的回报。

所以跟着

for($i = 0 ; $i < count( $matches[0] ) ; $i++ )
{ 
    var_dump($matches[0][ $i ] . "<br/>");
} 

你现在看到它匹配每次出现:

string '<a href='...'>AAA</a><br/>' (length=26)
string '<a href='...'>BBB</a><br/>' (length=26)
string '<a href='...'>CCC</a><br/>' (length=26)

-------- NEW EDIT ---------

所以现在你可以修改你的循环,以便包装匹配的每个a标签。

$result='';

for($i = 0 ; $i < count( $matches[0] ) ; $i++ )
{ 
    $result .= "<font ...>".$matches[0][ $i ] . "</font><br/>";
} 

var_dump($result);

你得到了

<font ...><a href='...'>AAA</a></font><br/><font ...><a href='...'>BBB</a></font><br/><font ...><a href='...'>CCC</a></font><br/>

---------- NEW EDIT ----------

正如你所建议的@Casimir et Hippolyte,你可以通过在模式中添加一个单词boudary来避免将“错误或不需要的”标记与abbr匹配:

$lvs_regex = "/<a\b.*?<\/a>/" ; 

并且可选地通过使用foreach而不是for循环来获得相同的结果。例如:

foreach($matches[0] as $matches)
{ 
    $result .= "<font ...>".$matches . "</font><br/>";
} 

link关于foreach内部行为,以防您深入了解该构造。

答案 1 :(得分:0)

$lvs_regex = "/<a.+<\/a>/U" ;

$lvs_test  = "click <a href='...'>AAA</a> now, <a href='...'>BBB</a> later, <a href='...'>CCC</a> tomorrow" ;

preg_match_all( $lvs_regex , $lvs_test , $matches ) ;
if ($matches) {
    foreach ($matches[0] as $match) {
        print $match."\n";
    }
}

结果是:

<a href='...'>AAA</a>
<a href='...'>BBB</a>
<a href='...'>CCC</a>

使用'ungreedy'特定人/ U

http://www.php.net/manual/fa/reference.pcre.pattern.modifiers.php