代码之家  ›  专栏  ›  技术社区  ›  Alex Angas Colin

如何在任意索引处选择匹配的正则表达式?

  •  0
  • Alex Angas Colin  · 技术社区  · 14 年前

    我有一根绳子,看起来像:

    ABC-DEF01-GHI54677-JKL!983-MnOP

    在每一个 - 几乎可以是任何字符重复任何次数。

    我使用的是这个正则表达式:

    [^-]*
    

    如何使其“匹配”第二个索引的匹配项(例如def01)?或第三个(GHI54677)或第四个(JKL!9988)?

    我使用的引擎不允许我指定匹配索引或附加代码-它必须在表达式中完成。

    3 回复  |  直到 14 年前
        1
  •  2
  •   eruciform    14 年前

    第二组parens将分别捕获“def”、“ghi”和“jkl”…

    ([^-]+-){1}([^-]+)
    ([^-]+-){2}([^-]+)
    ([^-]+-){3}([^-]+)
    

    如果这是Perl,则使第一组parens不捕获,即:

    # perl -de 0
    $_="ABC-DEF-GHI-JKL-MNO"
    p /(?:[^-]+-){1}([^-]+)/
      DEF
    p /(?:[^-]+-){2}([^-]+)/
      GHI
    p /(?:[^-]+-){3}([^-]+)/
      JKL
    
    $_="ABC-DEF01-GHI54677-JKL!9988-MNOP"
    p /(?:[^-]+-){1}([^-]+)/
      DEF01
    p /(?:[^-]+-){2}([^-]+)/
      GHI54677
    p /(?:[^-]+-){3}([^-]+)/
      JKL!9988
    

    说明:

    (?:  = non-capturing parens
    [^-] = a non-dash character
    +    = one or more
    -    = a dash
    )    = close paren
    {3}  = repeat 3 times
    

    这部分“吞食”1,2,3,或任何你喜欢的数字,块,留下下一套采取你正在寻找的。

    代替 + ,也可以使用 {1,} 意思是1对任意数字。

    如果块的大小可以为零,那么:

    ABC-GHI-JKL

    您想找到第二个,即“”(空字符串),然后使用 * 而不是 + . 或者你可以使用 {0,} ,表示0对任意数字。

        2
  •  1
  •   Michael Mrozek    14 年前

    您没有指定正在使用的语言/正则表达式引擎,但有一些(大多数?)让您反复地对同一个字符串应用匹配。例如,pcrecpp允许您执行以下操作:

    pcrecpp::StringPiece piece("ABC-DEF-GHI-JKL-MNO");
    pcrecpp::RE re("([^-]+)-?");
    unsigned int index = 3; // e.g., for GHI
    
    std::string group;
    for(unsigned int i = 0; i < index; i++)
        re.Consume(&piece, &group);
    
    // group now contains "GHI". Calling Consume again would give it JKL
    
        3
  •  0
  •   Michael Mrozek    14 年前

    根据你的修改,答案是不同的:你只是想要这个吗?

    (?:[^-]+-){index-1}([^-]+)
    

    非捕获组匹配 index-1 子块,因此 index=3 它匹配 ABC-DEF01- ,然后捕获组匹配 GHI54677