Regex.Matches 返回每行一个匹配项,而不是每个“单词”一个。

4

我很难理解以下表达式\\[B.+\\]和代码为什么会返回1个匹配项:

string r = "\\[B.+\\]";
return Regex.Matches(Markup, sRegEx);

我希望找到在变长的HTML字符串Markup中,以B为前缀并用方括号括起来(称之为“标记”)的所有实例。该字符串不包含换行符。

如果该字符串包含[BName],我将获得一个匹配 - 好的。

如果该字符串包含[BName] [BAddress],我只会得到一个匹配 - 为什么?

如果该字符串包含[BName][BAddress],我也只会得到一个匹配。

在一些基于Web的正则表达式测试工具中,我注意到如果文本包含CR字符,则每行都会获得一个匹配 - 但我需要一种指定返回独立于换行符的匹配的方法。

我还在MatchCollection的Groups和Captures集合中探索,但无济于事 - 始终只有一个结果。

3个回答

7
您只得到了一个匹配,因为默认情况下,.NET正则表达式是“贪婪”的;它们尝试在单个匹配中尽可能多地匹配。
因此,如果您的值是[BName] [BAddress],您将获得一个匹配-它将匹配整个字符串;因此,它将从开头的[B开始一直匹配到最后一个],而不是第一个。如果您想要两个匹配,请改用此模式:\[B.+?\]
+后面的?告诉匹配引擎尽可能少地匹配...留下第二组作为自己的匹配。
Slaks还注意到了一个很好的选项;明确指定您不希望将结束]作为内容的一部分进行匹配,如下所示:\[B[^]]+\]。这使您的匹配'贪婪',在某些其他情况下可能有用。在这种特定情况下,可能没有太大区别-但根据您可能正在处理的数据/模式,这是需要记住的重要事情。
顺便说一句,我建议使用C#“字面字符串”说明符@来设置正则表达式模式,以便您无需在正则表达式模式中进行双倍转义;所以我会这样设置模式:
string pattern = @"\[B.+?\]";

这使得更加复杂的正则表达式变得更易于理解。

1
太棒了 - 指令提示符写得非常好,甚至还包括了一些额外的技巧!非常感谢。 - James Rutledge

1
尝试使用正则表达式字符串\\[B.+?\\]。单独使用.+(同样适用于.*)将匹配尽可能多的字符,而.+?(或.*?)将匹配满足表达式其余部分的最少数量的字符。

+1 的意思是说,可以使用 ? 量词修饰符来处理 * 量词。无论你是否相信,? 也可以用于 ? 量词。请注意,在使用 *? 量词时,如果可能的话,它们将尝试匹配 0 次。有时这可能会导致看似奇怪的结果。 - Andrew Barber

1

.+ 是贪婪匹配,它会尽可能地匹配。
在你的第二个例子中,它匹配了 BName] [BAddress

你应该写成 \[B[^\]]+\]
[^\]] 匹配除了 ] 以外的所有字符,因此它被迫在第一个 ] 停止。


+1; 这可能是比我最初发布的单一选项更好的选择,这取决于所涉及的数据。在情况下可能不会有任何区别,但在匹配类似“标签”的内容时,在一般情况下可能更好。我已经将其(带有归属)添加到我的答案中。 - Andrew Barber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接