被替换文本末尾的额外字符

2022-09-03 09:31:38

在PHP和Java中,我申请并得到了.我应用了对称模式,得到了一个不对称的结果!为什么?我想知道为什么它的输出不是?/^[^\pL]*|[^\pL]*$/-A-*A***A*

模式说,除了字符串末尾的字母之外,所有的东西都应该用替换,这也是贪婪的,应该把所有非字母的东西都替换在一起。*

RegexBuddy中的Alos注释我得到了我所期望的。*A*

更新:我简化了问题,以集中我的主要关注点。


答案 1
#^[^\pL]+|[^\pL]+$#u

替换为 。结合使用并不像人们预期的那样有效。在正则表达式引擎如何工作的奇怪结果中,将找到个匹配项。使用修复它。*+*$X*$X*+

解释

[^\pL]*$

让我们看一下正则表达式的这一部分,该部分未按预期工作。为什么它在一些字符串的末尾放了两个's?*

  1. 考虑替换第一组短划线后的第三个示例字符串:---A---

    *A---$
    
  2. 正则表达式引擎在此处找到正则表达式的匹配项:

    *A---$
      ^
    
  3. 并替换为星号:"---"

    *A*$
      ^
    
  4. 然后,它将其内部光标移动到替换字符串的右侧。

    *A*$
       ^
    
  5. 它从此光标位置开始,并查找另一个匹配项。它找到了一个!它找到 — 空字符串! 由 0 个或多个非字母 () 组成,并且它锚定在字符串 () 的末尾,因此它是有效的匹配项。当然,它找到了空字符串,但这是允许的。""""[^\pL]*$

    这是出乎意料的,因为它再次匹配了锚点。这不是错的吗?它不应该再次匹配,不是吗?嗯,实际上,它应该,而且确实如此。它可以再次匹配,因为它不是输入字符串中的实际字符 - 它是一个零宽度断言。它不会在第一次替换时“用完”。 允许匹配两次。$$$$$

  6. 因此,它用星号“替换”空字符串。这就是为什么你最终会得到两个星号。""

    *A**$
       ^
    
  7. 如果正则表达式引擎返回到步骤 4,它将找到另一个空字符串并添加另一个星号。从概念上讲,那里有无限数量的空字符串。为了避免这种情况,引擎不允许下一场比赛在与前一场比赛相同的位置开始。此规则可防止它进入无限循环。


答案 2

正确的正则表达式是这样的:

$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字符,因此第一个元素将保持不变。


推荐