【问题标题】:Regex: captures, groups, confusion正则表达式:捕获、分组、混淆
【发布时间】:2010-09-30 20:14:11
【问题描述】:

我似乎无法弄清楚 Regex (.net) 中的捕获 + 组。

假设我有以下输入字符串,其中每个字母实际上是更复杂的正则表达式的占位符(因此简单的字符排除不起作用):

CBDAEDBCEFBCD

或者,更一般地说,这是一个用“正则表达式”编写的字符串模式:

(C|B|D)*A(E*)(D|B|C)*(E*)F(B|C|D)*

只有一个 A 和一个 F。 我需要将发生在 A 之后和 F 之前的 B、C、D 的所有实例(在我的应用程序中是更复杂的组)作为单独的“捕获”(或匹配或组)捕获。我还需要 A 和 F。我不需要'不需要 E。我不需要 A 之前的 C,B,D 或 F 之后的 B,C,D。

我希望正确的结果是:

Groups["start"] (1 capture) = A
Groups["content"] (3 captures)  
  Captures[0] = D  
  Captures[1] = B
  Captures[2] = C
Groups["end"] (1 capture) = F

我尝试了几次微不足道的尝试,但都没有成功。

仅“不正确”捕获上述示例字符串中 EF 之前的最后一个 C(以及正确的 start = A,end = F)

(?<=(?<start>A)).+(?<content>B|C|D).+(?=(?<end>F))

与上面的结果相同(只是在 (?B|C|D) 之后添加了一个 + )

(?<=(?<start>A)).+(?<content>B|C|D)+.+(?=(?<end>F))

摆脱了环顾四周的东西......结果与上面相同

(?<start>A).+(?<content>B|C|D)+.+(?<end>F)

然后我那没用的大脑罢工了。

那么,解决这个问题的正确方法是什么?是否真的需要环顾四周?

谢谢!

【问题讨论】:

    标签: .net regex


    【解决方案1】:

    是的,忘记环视,它们只会使事情变得不必要地复杂化。但我怀疑如果你先做那个.+ relucant,你最终的正则表达式会起作用:

    (?<start>A).+?(?<content>B|C|D)+.+(?<end>F)
    

    编辑:是的

    string s = "CBDAEDBCEFBCD";
    Regex r = new Regex(@"(?<start>A).+?(?<content>B|C|D)+.+(?<end>F)");
    
    foreach (Match m in r.Matches(s))
    {
      Console.WriteLine(@"Groups[""start""] = {0}", m.Groups["start"]);
      foreach (Capture c in m.Groups["content"].Captures)
      {
        Console.WriteLine(@"Capture[""content""] = {0}", c.Value);
      }
      Console.WriteLine(@"Groups[""end""] = {0}", m.Groups["end"]);
    }
    

    输出:

    Groups["start"] = A
    Capture["content"] = D
    Capture["content"] = B
    Capture["content"] = C
    Groups["end"] = F
    

    【讨论】:

    • 真的!所以不需要环顾四周吧……太棒了。
    • @Jimmy:在这种情况下,是的,不需要环视。但它们确实有它们的用途。 :P
    【解决方案2】:

    既然你说的是C,B,D 的所有实例,我想你会想为[CBD]* 使用分组另外,如果你只是想在A 之后但@ 之前寻找一些东西987654325@,那么您应该可以使用这些文字以及一些排除项。

    这是我想出的一个模式。组$4 应包含字母DBC

    ([^A]*)(A)([^CBDF]*)([CBD]*)([^F]*)(F)(.*)
    

    这是this pattern in action 的示例。

    问题是,如果原始字符串是CBDAEDEBECEFBCD,你想要什么?

    【讨论】:

    • 抱歉,所有字母都是更复杂组的占位符(我会更新问题) - 所以我不能只使用文字排除。您建议的字符串 CBDAEDEBECEFBCD 根本不应该匹配 - 在 A 和第一个 (B|C|D) 之间只有一堆 E,而在 F 之前还有一堆 E。同样,在我的应用程序中,它们不仅仅是 E,它们只是我不需要的文本。
    • 如果是这种情况,那么环顾四周可能是您唯一的选择。
    • 你能推荐一个可行的看看吗?即使环顾四周,我仍然无法让它工作。
    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多