我不确定其中一个是否比另一个“更好”,为什么会这样,但我有一个看起来像这样的原始字符串:
$string = '/random_length_user/file.php';
现在,有两种方法可以匹配它,第一种方式,使用我的新朋友,后视和第二种,没有:
preg_match("%(?<=^/)([^/]*)%", $string, $capture);
preg_match("%^/([^/]*)%", $string, $capture);
他们按顺序返回:
Array
(
[0] => random_length_user
)
Array
(
[0] => /random_length_user
[1] => random_length_user
)
基本上我使用look-behind在$ capture [0]中获得我想要的结果,而在$ capture [1]中没有。现在问题是......是否有理由偏好这些方法中的一种而不是另一种?
答案 0 :(得分:3)
它可能与preg_match
无关,但在使用preg_replace
时会很重要,因为它会影响要替换的内容。
当您进行全局匹配时,这也可能是一个问题,因为捕获组将消耗字符,而外观不会
琐碎的例子:
/(?<=a)a/g
与'aaaa'
一致Array('a', 'a', 'a')
/(a)a/g
与'aaaa'
一致Array('aa', 'aa')
答案 1 :(得分:1)
问题在于,后视方法并不灵活;当你开始处理可变长度匹配时,它就会崩溃。例如,假设您要在示例中提取文件名,并且您不知道目录的名称。捕获组技术仍然可以正常工作:
preg_match("%^/\w+/([^/]*)%", '/random_length_user/file.php');
Array
(
[0] => /random_length_user/file.php
[1] => file.php
)
...但是后视方法没有,因为lookbehind表达式只能匹配固定数量的字符。但是,有一个更好的选择:\K
,MATCH POINT RESET运算符。无论你把它放在哪里,正则表达式引擎都假装比赛真的从那里开始。因此,您可以获得与使用lookbehind相同的结果,没有固定长度限制:
preg_match('%^/\w+/\K[^/]+$%', '/random_length_user/file.php');
Array
(
[0] => file.php
)
据我所知,此功能仅适用于Perl 5.10+以及由PCRE库驱动的工具(如PHP的preg_
函数)。有关PCRE参考,请参阅the manpage并搜索(F3)\K
。