没有行开头和结尾终结符的Regex.Replace有一些非常奇怪的效果……这里发生了什么?

在回答这个问题时, C#Regex Replace和*提出了问题存在的原因。 在播放时我制作了以下代码:

string s = Regex.Replace(".A.", "\w*", "B"); Console.Write(s); 

这有输出: B.BB.B

我得到0长度字符串在之前和之后匹配. 字符,但为什么A被2个B取代。

我可以理解B.BBB.B替换ABBB两侧的零长度字符串但实际结果让我感到困惑 – 任何帮助都值得赞赏。

或者正如AakashM所说:

为什么Regex.Matches("A", "\w*").Count等于2 ,而不是13

因为\ w *是一个贪婪的正则表达式,它试图找到最大的序列。 因此它在点之前匹配"nothing" ,然后在两个点之间"nothing"A然后在第二个点之前"nothing" ,最后在第二个点之后"nothing"

\ w之后有一颗星

它意味着“ 或多”,这意味着:

  • 第一个符号是一个点,它不是\ w所以这里有零\ w ,由B替换
  • 接下来我们有一个点本身,这是不可替换的
  • A被B取代
  • 在下一个点之前为零\ w,由B替换
  • 点,不可替换
  • 行结束,零\ w因此再次替换为B.

表达式\w{0,}将具有相同的效果。

如果你想避免它,请使用’plus’,意思是’至少一个’: \w+

这是相同的行为

Regex.Replace("", "\w*", "B")导致B
Regex.Replace("A", "\w*", "B")导致BB

在Regexr上看到它

对于字符串“.A。” \w*在第一个点之前匹配空字符串,然后在“A”上,“A”之后的空字符串和最后一个点之后的空字符串。

说明

你可以想到吃掉这些字符的模式, \w*吃了“A”,下一个字符是一个点,所以这个匹配完成并被替换。 但是模式继续匹配的起始位置仍然在A和点之间。 点不能匹配,因此它匹配点之前的空字符串,但是此位置完成,下一个开始位置在点之后。

默认情况下,它是贪婪匹配,因此搜索最大匹配。 这就是你得到那个结果的原因。

如果你不情愿地这样做,就像这样

 string s = Regex.Replace(".A.", "\\w*?", "B"); 

你会得到这个结果,因为它找到了最小的匹配。

 B.BAB.B