代码之家  ›  专栏  ›  技术社区  ›  Yaakov Ellis NevilleDNZ

匹配模式的正则表达式,只要它前面没有不同的模式

  •  6
  • Yaakov Ellis NevilleDNZ  · 技术社区  · 14 年前

    我需要一个用于文本替换的正则表达式。示例:要匹配的文本是 ABC (可以用方括号括起来),替换文本是 DEF . 这已经足够基本了。复杂的是我 不要 想要匹配 前面有模式时的文本 \[[\d ]+\]\.

    下面是一些要匹配的源文本示例,以及在正则表达式替换之后的结果:

    1. [xxx xxx].[ABC] > [xxx xxx].[ABC] (does not match - first part fits the pattern)
    2. [xxx xxx].ABC   > [xxx xxx].ABC   (does not match - first part fits the pattern)
    3. [xxx.ABC        > [xxx.DEF        (matches - first part has no closing bracket)
    4. [ABC]           > [DEF]           (matches - no first part)
    5. ABC             > DEF             (matches - no first part)
    6. [xxx][ABC]      > [xxx][DEF]      (matches - no period in between)
    7. [xxx]. [ABC]    > [xxx] [DEF]     (matches - space in between)
    

    归根结底是:我如何指定前面的模式,当出现如所述时 防止

    1 回复  |  直到 14 年前
        1
  •  14
  •   Jeremy W. Sherman    14 年前

    你想要一个消极的表情。这些看起来像 (?<!pattern) ,所以:

    (?<!\[[\d ]+\]\.)\[?ABC\]?
    

    注意,这不会强制ABC周围有一对匹配的方括号;它只允许在前面有一个可选的左括号,后面有一个可选的右括号。如果要强制匹配对或不匹配对,则必须使用替换:

    (?<!\[[\d ]+\]\.)(?:ABC|\[ABC\])
    

    这使用非捕获圆括号来分隔替换。如果你真的想捕捉ABC,你可以把它变成一个捕捉组。

    第一个表达式似乎失败的原因是它匹配 ABC] [ 是可选的,所以不匹配。方法是移动可选的打开支架 [ 对断言背后的负面看法,如:

    (?<!\[[\d ]+\]\.\[?)ABC\]?
    

    它匹配和不匹配的示例:

    [123].[ABC]: fail (expected: fail)
    [123 456].[ABC]: fail (expected: fail)
    [123.ABC: match (expected: match)
        matched: ABC
    ABC: match (expected: match)
        matched: ABC
    [ABC]: match (expected: match)
        matched: ABC]
    [ABC[: match (expected: fail)
        matched: ABC
    

    [ ] ,正如第二种模式所预期的那样,更为棘手,但这似乎奏效了:

    (?:(?<!\[[\d ]+\]\.\[)ABC\]|(?<!\[[\d ]+\]\.)(?<!\[)ABC(?!\]))
    

    它匹配和不匹配的示例:

    [123].[ABC]: fail (expected: fail)
    [123 456].[ABC]: fail (expected: fail)
    [123.ABC: match (expected: match)
        matched: ABC
    ABC: match (expected: match)
        matched: ABC
    [ABC]: match (expected: match)
        matched: ABC]
    [ABC[: fail (expected: fail)
    

    示例是使用以下代码生成的:

    // Compile and run with: mcs so_regex.cs && mono so_regex.exe
    using System;
    using System.Text.RegularExpressions;
    
    public class SORegex {
      public static void Main() {
        string[] values = {"[123].[ABC]", "[123 456].[ABC]", "[123.ABC", "ABC", "[ABC]", "[ABC["};
        string[] expected = {"fail", "fail", "match", "match", "match", "fail"};
        string pattern = @"(?<!\[[\d ]+\]\.\[?)ABC\]?";  // Don't force [ to match ].
        //string pattern = @"(?:(?<!\[[\d ]+\]\.\[)ABC\]|(?<!\[[\d ]+\]\.)(?<!\[)ABC(?!\]))";  // Force balanced brackets.
        Console.WriteLine("pattern: {0}", pattern);
        int i = 0;
        foreach (string text in values) {
          Match m = Regex.Match(text, pattern);
          bool isMatch = m.Success;
          Console.WriteLine("{0}: {1} (expected: {2})", text, isMatch? "match" : "fail", expected[i++]);
          if (isMatch) Console.WriteLine("\tmatched: {0}", m.Value);
        }
      }
    }