preg_replace双重替换

时间:2012-12-04 14:29:28

标签: php regex preg-replace

我从正则表达式中获得了一些意想不到的结果,这意味着要替换名称空间上的类名。替换似乎发生了两次,因此被替换的类名是重复的(参见下面的示例)。

我实际上已经通过将reg ex更改为匹配1或更多(+)而不是0或更多(*)来解决问题,这实际上对于我想要的更准确。< / p>

然而,我有点困惑为什么我首先遇到问题。

以下是问题的一个示例:

$classns  = 'components\groups\GroupsController';
$newclass = 'GroupsAccess';
$classns = preg_replace('/[^\\\\]*$/', $newclass, $classns);
echo $classns;

结果

components\groups\GroupsAccessGroupsAccess

预期

components\groups\GroupsAccess

*是否可能与字边界或某种性质相匹配?

对我来说令人困惑的部分是使用相同正则表达式的preg_match只显示一个结果,因此它似乎是preg_match如何运行正则表达式的特定内容。

e.g。

preg_match('/[^\\\\]*$/', $classns, $m);
var_dump($m);

结果

array(1) { [0]=> string(12) "GroupsAccess" }

2 个答案:

答案 0 :(得分:5)

*与字边界不匹配,匹配空字符串

您的表达式首先匹配

  

components \ groups \ GroupsController

并且$是一个匹配位置的锚点,它位于字符串结尾之前(或者字符串结尾之前的\n)。

所以在第一次匹配之后,正则表达式解析器的位置在最后一个“r”之后和字符串结尾之前,当它再次尝试匹配你的正则表达式时。它会找到一个匹配==&gt; 0次出现/(空字符串),后跟字符串结尾。

然后它继续前进,识别字符串的结尾并完成。

答案 1 :(得分:2)

缩小它,这也显示两个匹配:

preg_match_all('/a*$/', 'a', $m);`

Python具有相同的行为:

>>> re.findall('a*$', 'a')
['a', '']

Perl也是如此:

>>> my @m = 'a' =~ /a*$/g;
>>> foreach (@m) { print "$_\n"; }
a
<blank>

似乎正则表达式引擎匹配'a'和跟随它的空字符串''。从技术上讲这是正确的,虽然这是令人惊讶的。 'a'是一个锚定在搜索字符串末尾的字符串,''也是。

匹配的一个基本规则是匹配不重叠。一旦找到匹配,正则表达式引擎将继续在上一场比赛结束时搜索下一场比赛。我没想到的是,锚$可以被重用,大概是因为它是零宽度断言,而不是实际的子串匹配。