替换文本末尾的额外字符

PHP*_*Pst 15 php java regex pcre

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

模式说除了字符串末尾的字母之外的所有东西都应该被替换*,它也是贪婪的并且应该一起替换所有非字母的东西.

在RegexBuddy的Alos笔记我得到*A*的就是我的期望.

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

Joh*_*ica 27

#^[^\pL]+|[^\pL]+$#u
Run Code Online (Sandbox Code Playgroud)

替换*+.使用*结合$完全不是那么回事正如人们所期望的那样.在正则表达式引擎如何工作的奇怪结果中,X*$将找到两个匹配X*.使用+修复它.

说明

[^\pL]*$
Run Code Online (Sandbox Code Playgroud)

让我们看一下正则表达式的这一部分,这部分没有按预期工作.为什么它会把两个*字符串放在一些字符串的末尾?

  1. ---A---在替换第一组破折号后,请考虑第三个示例字符串:

    *A---$
    
    Run Code Online (Sandbox Code Playgroud)
  2. 正则表达式引擎在这里找到正则表达式的匹配:

    *A---$
      ^
    
    Run Code Online (Sandbox Code Playgroud)
  3. 并替换"---"为星号:

    *A*$
      ^
    
    Run Code Online (Sandbox Code Playgroud)
  4. 然后它将其内部光标移动到替换字符串的右侧.

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

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

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

    *A**$
       ^
    
    Run Code Online (Sandbox Code Playgroud)
  7. 如果正则表达式引擎返回到步骤4,它将找到另一个空字符串并添加另一个星号.从概念上讲,那里有无数个空字符串.为避免这种情况,引擎不允许下一个匹配从与前一个匹配的位置开始.此规则使其无法进入无限循环.

  • 要添加的一件事:它第三次不匹配的原因是因为上一场比赛是空的.在这种情况下,引擎不允许下一场比赛从同一位置开始,因为之后所有以下比赛都将从那里开始.它会陷入无限循环. (2认同)

anu*_*ava 7

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

$arr = preg_replace('#^[^\pL]+|[^\pL]+$#','*', 
           array('A','-A-','---A---','-+*A*+-','------------A------------'));
Run Code Online (Sandbox Code Playgroud)

注意+而不是*.这将给出输出:

Array
(
    [0] => A
    [1] => *A*
    [2] => *A*
    [3] => *A*
    [4] => *A*
)
Run Code Online (Sandbox Code Playgroud)

PS:请注意,由于A之前和之后没有非alpha字符这一事实,第一个元素将保持不变.