+ -
当前位置:首页 → 问答吧 → php正则的捕获组为什么只能保存最后一次捕获的内容?

php正则的捕获组为什么只能保存最后一次捕获的内容?

时间:2011-12-08

来源:互联网

比如有这样一个字符串: <div><ul id="test1"><li>aaaaa</li><li>bbbbb</li></ul><ul id="test2"><li>cccccc</li><li>ddddd</li></ul></div>

我想一次性将id为test1的ul标签里的li标签包含的文本都提取出来。写了如下的表达式:
<ul[^>]*id="test1"[^>]*>(<li>(?:<text>[^<]*)</li>)+[^<]*</ul>,用preg_match来匹配,因为整个表达式我只需要匹配一次就足够了。

这个表达式执行完毕后捕获组text里只保存了bbbbb,而没有保存aaaaa。为什么会这样?难道php的捕获组只能保存最后一次捕获的内容?
听说php的正则也不支持平衡组的,我也试过php下的平衡组,是没成功。会不会是因为上面这个原因?平衡组需要能够压栈,可php捕获第二次的时候,就将第一次的数据丢了?

要完成上面的匹配,我用php只能分步进行,第一步先匹配出id为test1的ul包含的内容,第二步再用preg_match_all来匹配里面的所有li包含的文本。

不知道有没有什么办法用php可以不用分步,一次性匹配出来的?谢谢!

作者: yuzhouxian1989   发布时间: 2011-12-08

preg_match_all 试试

或者用用这个试试 <li>.*</li>

作者: xiachao2008   发布时间: 2011-12-08

引用 1 楼 xiachao2008 的回复:
preg_match_all 试试

或者用用这个试试 <li>.*</li>

preg_match_all没用,因为本来整个表达式就只匹配一次。id为test1的ul在整个字符串里只有一个。
用<li>.*</li>的话,一者是贪婪匹配,会匹配出aaaaa</li><li>bbbbb。另外我想要的是aaaaa和bbbbb,希望返回的结果中match数组的test(捕获组名)元素也为一个数组,包含aaaaa和bbbbb两个值。之所以test组会成功捕获两次,是因为我的表达式里用了 (<li>(?:<text>[^<]*)</li>)+,是这个+在起作用。
我现在返回的match结果是:
Array
(
  [0] => <ul id="test1"><li>aaaaa</li><li>bbbbb</li></ul>
  [1] => <li>bbbbb</li>
  [text] => bbbbb
  [2] => bbbbb
)

作者: yuzhouxian1989   发布时间: 2011-12-08

顺便更正一下,主帖里的正则表达式不小心打错,(?:<text> 处应为 (?<text 多了一个: 。我自己测试的时候没打错,发帖的时候才打错的。

作者: yuzhouxian1989   发布时间: 2011-12-08

可以看到键名为1的元素只保存了 <li>bbbbb</li> ,而实际在匹配的时候,肯定也匹配到了 <li>aaaaa</li>的,因为第0个元素里出现了。而除了 <li>(?<text>[^<]*)</li> 之外,我的表达式里没有其他部分可以匹配到 <li>aaaaa</li> 的。

作者: yuzhouxian1989   发布时间: 2011-12-08