PHP的preg_Match()返回最后一场比赛的位置
与
preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE);
是否可以反向搜索字符串?即返回该模式在主题中最后一次出现的位置,类似于strripos
。
还是必须用preg_match_all
返回所有匹配项的位置并使用$matches
的最后一个元素?
解决方案
php没有从右向左搜索字符串的正则表达式方法(如.NET所示)。有几个可能的方法可以解决这个问题(这个列表不是详尽的,但它可能为您自己的解决方法提供一些想法):
- 使用
preg_match_all
和PREG_SET_ORDER
标志和end($matches)
将得到最后一个匹配集 - 使用
strrev
反转字符串并构建要与preg_Match一起使用的反转模式 - 使用
preg_match
并构建一个锚定在字符串末尾的模式,以确保在字符串末尾之前不再出现搜索到的掩码 - 在目标之前使用贪婪的量词,
K
在您想要的位置开始匹配结果。到达字符串末尾后,正则表达式引擎将回溯,直到找到匹配项。
模式/x[A-Z]+d/
的字符串$str = 'xxABC1xxxABC2xx'
的示例
方法1:查找所有匹配项并显示最后一个匹配项。
if ( preg_match_all('/x[A-Z]+d/', $str, $matches, PREG_SET_ORDER) )
print_r(end($matches)[0]);
Demo
方法2:查找颠倒的字符串与颠倒的模式的第一个匹配,并显示颠倒的结果。
if ( preg_match('/d[A-Z]+x/', strrev($str), $match) )
print_r(strrev($match[0]));
Demo
请注意,反转模式并不总是那么容易。
方法3:从x跳到x,并检查字符串末尾是否没有其他x[A-Z]+d
匹配项。
if ( preg_match('/x[A-Z]+d(?!.*x[A-Z]+d)/', $str, $match) )
print_r($match[0]);
Demo
变体:
使用懒惰的量词
if ( preg_match('/x[A-Z]+d(?!.*?x[A-Z]+d)/', $str, $match) )
print_r($match[0]);
或使用";缓和的量词
if ( preg_match('/x[A-Z]+d(?=(?:(?!x[A-Z]+d).)*$)/', $str, $match) )
print_r($match[0]);
当您事先知道哪些地方最有可能发生匹配时,在这些变体之间进行选择可能会很有趣。
方法4:转到字符串末尾并回溯,直到找到x[A-Z]+d
匹配。K
从匹配结果中删除字符串的开头。
if ( preg_match('/^.*Kx[A-Z]+d/', $str, $match) )
print_r($match[0]);
方法4(一种更手动的变体):为了限制回溯步骤,您可以贪婪地从字符串的开头开始前进,按原子组逐个原子组,并以相同的方式按原子组而不是按字符回溯。
if ( preg_match('/^(?>[^x]*Kx)+[A-Z]+d/', $str, $match) )
print_r($match[0]);
相关文章