.net Regex.Replace中的错误?

Aut*_*act 10 .net regex

以下代码......

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        var r = new Regex("(.*)");
        var c = "XYZ";
        var uc = r.Replace(c, "A $1 B");

        Console.WriteLine(uc);
    }
}
Run Code Online (Sandbox Code Playgroud)

.Net小提琴链接

产生以下输出......

一个XYZ BA B.

你认为这是对的吗?

输出不应该......

一个XYZ B.

我想我在这里做了些蠢事.如能帮助我理解这个问题,我将不胜感激.


这是有趣的事情......

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        var r = new Regex("(.*)");
        var c = "XYZ";
        var uc = r.Replace(c, "$1");

        Console.WriteLine(uc);
    }
}
Run Code Online (Sandbox Code Playgroud)

.Net小提琴

输出...

XYZ

nha*_*tdh 6

至于为什么引擎返回2个匹配,这是由于.NET(也是Perl和Java)处理全局匹配的方式,即在输入字符串中查找给定模式的所有匹配.

该过程可以描述如下(当前索引通常在搜索开始时设置为0,除非指定):

  1. 从当前索引执行搜索.
  2. 如果没有匹配:
    1. 如果当前索引已经指向字符串的末尾(当前索引> = string.length),则返回到目前为止的结果.
    2. 将当前索引增加1,转到步骤1.
  3. 如果main match($0)非空(消耗了至少一个字符),则添加结果并将当前索引设置为main match($0)的末尾.然后转到第1步.
  4. 如果main match($0)为空:
    1. 如果上一个匹配项为非空,请添加结果并转到步骤1.
    2. 如果上一个匹配为空,则回溯并继续搜索.
    3. 如果回溯尝试找到非空匹配,则添加结果,将当前索引设置为匹配结束并转到步骤1.
    4. 否则,将当前索引增加1.转到步骤1.

引擎需要检查空匹配; 否则,它将以无限循环结束.设计者识别空匹配的使用(例如,将字符串拆分为字符),因此必须设计引擎以避免永远卡在某个位置.

此过程解释了为什么最后会出现空匹配:由于搜索是在(.*)匹配后的字符串末尾(索引3)进行的abc,并且(.*)可以匹配空字符串,因此会找到空匹配.并且引擎不会产生无限数量的空匹配,因为最后已经找到空匹配.

 a b c
^ ^ ^ ^
0 1 2 3
Run Code Online (Sandbox Code Playgroud)

第一场比赛:

 a b c
^     ^
0-----3
Run Code Online (Sandbox Code Playgroud)

第二场比赛:

 a b c
      ^
      3
Run Code Online (Sandbox Code Playgroud)

使用上面的全局匹配算法,从同一索引开始只能有最多2个匹配,并且这种情况只能在第一个匹配为空匹配时发生.

请注意,如果主匹配为空,JavaScript只会将当前索引增加1,因此每个索引最多匹配1个匹配项.但是,在这种情况下(.*),如果使用全局标志g进行全局匹配,则会发生相同的结果:

(下面的结果来自Firefox,注意g标志)

> "XYZ".replace(/(.*)/g, "A $1 B")
"A XYZ BA  B"
Run Code Online (Sandbox Code Playgroud)