我有一个字符串可能看起来像这样:
$r = 'Filed under: <a>Group1</a>, <a>Group2</a>';
这是我目前使用的正则表达式:
preg_match_all("/Filed under: (?:<a.*?>([\w|\d|\s]+?)<\/a>)+?/", $r, $matches);
我希望正则表达式在()
内继续进行最后指定的+?
匹配。但它不会这样做。 ::叹息::
任何想法。我知道必须有一种方法可以在一个正则表达式中执行此操作,而不是将其分解。
答案 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;它更具可读性,更灵活,更易于维护。
编辑:虽然我给出的引用是针对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)
我希望正则表达式在()内部继续使用+指定匹配?最后。
+?
是一个懒惰的量词 - 它会尽可能少地匹配。换句话说,只需一次。
如果你想多次匹配,你需要一个贪婪的量词 - +
。
另请注意,正则表达式不能正常工作 - 匹配会在遇到标记之间的逗号后立即失败,因为您没有考虑到它。这可能需要纠正。