3

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

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

但是,我对为什么我首先遇到问题感到有些困惑。

这是问题的一个例子:

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

结果

components\groups\GroupsAccessGroupsAccess

预期的

components\groups\GroupsAccess

* 是否有可能匹配单词边界或类似的东西?

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

例如

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

结果

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

2 回答 2

5

不匹配单词边界,*它匹配空字符串

你的表达最初是匹配的

组件\组\组控制器

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

因此,在第一次匹配之后,正则表达式解析器的位置在最后一个“r”之后和字符串结尾之前,当它再次尝试匹配您的正则表达式时。它会再找到一个匹配 ==> 0 次出现的/(空字符串),然后是字符串的结尾。

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

于 2012-12-04T14:45:10.087 回答
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'是一个锚定在搜索字符串末尾的字符串,''.

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

于 2012-12-04T14:55:57.250 回答