没有行开头和结尾终结符的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
替换A
或BBB
两侧的零长度字符串但实际结果让我感到困惑 – 任何帮助都值得赞赏。
或者正如AakashM所说:
为什么Regex.Matches("A", "\w*").Count
等于2
,而不是1
或3
?
因为\ 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