被替换文本末尾的额外字符
在PHP和Java中,我申请并得到了.我应用了对称模式,得到了一个不对称的结果!为什么?我想知道为什么它的输出不是?/^[^\pL]*|[^\pL]*$/
-A-
*A**
*A*
模式说,除了字符串末尾的字母之外,所有的东西都应该用替换,这也是贪婪的,应该把所有非字母的东西都替换在一起。*
RegexBuddy中的Alos注释我得到了我所期望的。*A*
更新:我简化了问题,以集中我的主要关注点。
在PHP和Java中,我申请并得到了.我应用了对称模式,得到了一个不对称的结果!为什么?我想知道为什么它的输出不是?/^[^\pL]*|[^\pL]*$/
-A-
*A**
*A*
模式说,除了字符串末尾的字母之外,所有的东西都应该用替换,这也是贪婪的,应该把所有非字母的东西都替换在一起。*
RegexBuddy中的Alos注释我得到了我所期望的。*A*
更新:我简化了问题,以集中我的主要关注点。
#^[^\pL]+|[^\pL]+$#u
替换为 。结合使用并不像人们预期的那样有效。在正则表达式引擎如何工作的奇怪结果中,将找到两个匹配项。使用修复它。*
+
*
$
X*$
X*
+
[^\pL]*$
让我们看一下正则表达式的这一部分,该部分未按预期工作。为什么它在一些字符串的末尾放了两个's?*
考虑替换第一组短划线后的第三个示例字符串:---A---
*A---$
正则表达式引擎在此处找到正则表达式的匹配项:
*A---$
^
并替换为星号:"---"
*A*$
^
然后,它将其内部光标移动到替换字符串的右侧。
*A*$
^
它从此光标位置开始,并查找另一个匹配项。它找到了一个!它找到 — 空字符串! 由 0 个或多个非字母 () 组成,并且它锚定在字符串 () 的末尾,因此它是有效的匹配项。当然,它找到了空字符串,但这是允许的。""
""
[^\pL]*
$
这是出乎意料的,因为它再次匹配了锚点。这不是错的吗?它不应该再次匹配,不是吗?嗯,实际上,它应该,而且确实如此。它可以再次匹配,因为它不是输入字符串中的实际字符 - 它是一个零宽度断言。它不会在第一次替换时“用完”。 允许匹配两次。$
$
$
$
$
因此,它用星号“替换”空字符串。这就是为什么你最终会得到两个星号。""
*A**$
^
如果正则表达式引擎返回到步骤 4,它将找到另一个空字符串并添加另一个星号。从概念上讲,那里有无限数量的空字符串。为了避免这种情况,引擎不允许下一场比赛在与前一场比赛相同的位置开始。此规则可防止它进入无限循环。
正确的正则表达式是这样的:
$arr = preg_replace('#^[^\pL]+|[^\pL]+$#','*',
array('A','-A-','---A---','-+*A*+-','------------A------------'));
请注意,而不是 。这将给出输出:+
*
Array
(
[0] => A
[1] => *A*
[2] => *A*
[3] => *A*
[4] => *A*
)
PS:请注意,由于A之前和之后没有非alpha字符,因此第一个元素将保持不变。