代码之家  ›  专栏  ›  技术社区  ›  Jimmy

regex:按不同顺序匹配组而不重复组

  •  14
  • Jimmy  · 技术社区  · 15 年前

    假设我有两条这样的线:

    XABY
    XBAY
    

    一个简单的正则表达式,两者都匹配,如下所示:

    X(AB|BA)Y
    

    但是,我有一个例子,其中a和b是复杂的字符串,我正在寻找一种方法,以避免必须指定它们中的每一个两次(在的每一侧)。有没有办法做到这一点(这可能比指定两次要简单得多)?

    谢谢

    4 回复  |  直到 11 年前
        1
  •  21
  •   Alan Moore Chris Ballance    14 年前
    X(?:A()|B()){2}\1\2Y
    

    基本上,当每个项目匹配时,使用一个空的捕获组来签出它,然后back引用确保所有项目都被签出。

    请注意,这依赖于未记录的regex行为,因此不能保证它在您的regex风格中工作——如果它工作了,也不能保证它会 持续 随着味道的发展而工作。但据我所知,它适用于所有支持反向引用的风格。(编辑:它在javascript中不起作用。)

    编辑: 你说你使用命名组来捕获匹配的一部分,这给正则表达式增加了很多视觉上的混乱,如果不是真正的复杂性的话。好吧,如果您碰巧使用了.NET正则表达式,您仍然可以使用简单的编号组作为“复选框”。下面是一个简单的例子,它在不知道月-日字符串的内部顺序的情况下查找和分离这些字符串:

      Regex r = new Regex(
        @"(?:
            (?<MONTH>Jan|Feb|Mar|Apr|May|Jun|Jul|Sep|Oct|Nov|Dec)()
            |
            (?<DAY>\d+)()
          ){2}
          \1\2",
        RegexOptions.IgnorePatternWhitespace);
    
      string input = @"30Jan Feb12 Mar23 4Apr May09 11Jun";
      foreach (Match m in r.Matches(input))
      {
        Console.WriteLine("{0} {1}", m.Groups["MONTH"], m.Groups["DAY"]);
      }
    

    这是因为在.NET中,命名组的存在对非命名组的顺序没有影响。命名组有分配给它们的编号,但这些编号以 之后 最后一个未命名的组。(我知道这似乎有点复杂,但有充分的理由这样做。)

    通常,您希望避免将命名和非命名捕获组一起使用,特别是在使用反向引用时,但我认为这种情况可能是一个合法的异常。

        2
  •  5
  •   Community CDub    8 年前

    您可以将regex片段存储在变量中,并执行以下操作:

    A=/* relevant regex pattern */
    B=/* other regex pattern */
    regex = X($A$B|$B$A)Y
    

    这样,您只需在每个regex的自己的行上指定一次,这将使维护变得更容易。

    旁注:你试图找到排列,这是可以的,因为你只看两个次区域。但是如果你想添加第三个(或第四个),你的regex排列会急剧增长(abc acb bac bca cab cba)-或者更糟。如果你需要沿着排列的道路前进,这里有一些很好的讨论 stackoverflow . 它用于字母排列,解决方案使用awk/bash/perl,但这至少给了您一个起点。

        3
  •  1
  •   limboy    15 年前

    试试这个

    X((A|B){2})Y
    
        4
  •  0
  •   BenMorel Manish Pradhan    11 年前

    如果有多个字符串,其中包含任何类型的字符,则最好使用:

    X(.)+Y
    

    只有数字

    X([0-9])+Y
    

    只信

    X([a-zA-Z])+Y
    

    字母和数字

    X([a-zA-Z][0-9])+Y