我有字符串:
<mml:mi>P</mml:mi><mml:mn>2</mml:mn>
并希望检索2
我的模式是:
/(?:<mml:)(mn|mi|mo)>(.+)(?:<\/mml:\1>)$/
返回值应为2,
但如果字符串是:
<mml:mi>P</mml:mi><mml:mi>s</mml:mi>
然后模式应该从第二组标签内返回s,但是从第一组内部返回P
P</mml:mi><mml:mi>s
按照以下建议更改模式时:
/<mml:(mn|mi|mo)>(.*?)<\/mml:\1>/sU
回报是一样的。 php的行是:
preg_match('/<mml:(mn|mi|mo)>(.*?)<\/mml:\1>/sU', '<mml:mi>P</mml:mi><mml:mi>s</mml:mi>', $ret, PREG_OFFSET_CAPTURE);
和$ ret包含:
Array
(
[0] => Array
(
[0] => <mml:mi>P</mml:mi><mml:mi>s</mml:mi>
[1] => 0
)
[1] => Array
(
[0] => mi
[1] => 5
)
[2] => Array
(
[0] => P</mml:mi><mml:mi>s
[1] => 8
)
)
当更改为已编辑的建议时,用?除去
/<mml:(mn|mi|mo)>(.*)<\/mml:\1>/sU
从第一次出现返回P,而不是从第二次出现的s。
答案 0 :(得分:1)
从我的手机打字,所以会很简短。
不是匹配任何字符(。+),而是匹配不下一个标记开头的任何字符([^&lt;] +)
这样您就不必担心使用反向引用,也不会抓住两个相同标记之间的所有内容。
(仔细检查我把插入符号放在哪里,这是我的头顶。)
要获取最后一次出现,请将整个正则表达式包装在()+
中/(<mml:(mn|mi|mo)>([^<]+)<\/mml:\2>)+/
答案 1 :(得分:0)
这是一个优化模式,它不仅比Tim更快地运行,preg_match()
将在输出数组中返回更少的元素:
~<m{2}l:(m[ino])>\K[^<](?=</m{2}l:\1>$)~
增强:
/
替换为~
,以避免转义以提高简洁性。{2}
m[ino]
\K
从模式中间开始全字符串匹配,有效地消除了额外捕获组的需要,以提高效率。[^<]
*注意,如果您想要的子字符串使用多个字符:[^<]+
$
。PHP实施:(Demo)
echo preg_match('~<m{2}l:(m[ino])>\K[^<](?=</m{2}l:\1>$)~','<mml:mi>P</mml:mi><mml:mi>s</mml:mi>',$out)?$out[0]:'fail';
输出:
s