【问题标题】:Regex.Matches returns one match per line, not per "word"Regex.Matches 每行返回一个匹配项,而不是每个“单词”
【发布时间】:2011-08-17 03:45:08
【问题描述】:

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

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

我想找到所有以 B 并用方括号括起来。

如果标记包含 [BName],我会得到一个匹配项 - good.

如果标记包含 [BName] [BAddress],我会得到一个匹配项 - 为什么?

如果标记包含[BName][BAddress],我也只会得到一个匹配项。

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

我还浏览了 MatchCollection 的 Groups 和 Captures 集合,但无济于事 - 总是只有一个结果。

【问题讨论】:

    标签: c# .net regex


    【解决方案1】:

    您只会得到一个匹配项,因为默认情况下,.NET 正则表达式是“贪婪的”;他们尝试尽可能多地匹配单个匹配项。

    因此,如果您的值为[BName][BAddress],您将有一个匹配项 - 将匹配整个字符串;所以它会从开头的 [B 一直匹配到 last ] - 而不是第一个。如果您想要两个匹配项,请改用此模式:\\[B.+?\\]

    + 之后的 ? 告诉匹配引擎尽可能少匹配...让第二组自己匹配。

    Slaks 还指出了一个很好的选择;明确指定您希望匹配结尾 ] 作为内容的一部分,如下所示:\\[B[^\\]]+\\] 这使您的匹配保持“贪婪”,这在其他情况下可能有用。在这种特定情况下,可能没有太大区别 - 但要记住这一点很重要,具体取决于您可能具体处理的数据/模式。


    附带说明,我建议将 C#“文字字符串”说明符 @ 用于正则表达式模式,这样您就不需要在正则表达式模式中双重转义;所以我会这样设置模式:

    string pattern = @"\[B.+?\]";
    

    这使得找出更复杂的正则表达式变得更加容易

    【讨论】:

    • 真棒 - 提示,写得很好,甚至包括一些额外的提示!非常感谢。
    【解决方案2】:

    改用正则表达式字符串\\[B.+?\\].+ 本身(.* 也是如此)将匹配尽可能多的字符,而 .+?(或 .*?)将匹配最少的字符数同时仍然满足其余字符表达方式。

    【讨论】:

    • +1 还提到 ? 量词修饰符在用作量词时也可以用于 *。信不信由你,它也可以用来对付?。请注意,对于*?,如果可能,它将尝试匹配0 次。有时这会导致看似奇怪的结果。
    【解决方案3】:

    .+ 是一个贪心匹配;它会尽可能匹配。
    在您的第二个示例中,它匹配 BName] [BAddress

    你应该写\[B[^\]]+\]
    [^\]]匹配除]之外的所有字符,所以它在第一个]之前被强制停止。

    【讨论】:

    • +1 ;这很可能是比我最初发布的单个更好的选择,具体取决于相关数据。在 this 的情况下它可能没有什么不同,但在匹配看起来像“标签”的东西的一般情况下可能会更好。我将此(带有归属)添加到我的答案中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2015-01-04
    • 2015-03-09
    相关资源
    最近更新 更多