Regex Pattern to Match, Excluding when… / Except between

前端 未结 6 886
别跟我提以往
别跟我提以往 2020-11-21 05:07

--Edit-- The current answers have some useful ideas but I want something more complete that I can 100% understand and reuse; that\'s why I set a bounty. Als

6条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-21 05:33

    Do three different matches and handle the combination of the three situations using in-program conditional logic. You don't need to handle everything in one giant regex.

    EDIT: let me expand a bit because the question just became more interesting :-)

    The general idea you are trying to capture here is to match against a certain regex pattern, but not when there are certain other (could be any number) patterns present in the test string. Fortunately, you can take advantage of your programming language: keep the regexes simple and just use a compound conditional. A best practice would be to capture this idea in a reusable component, so let's create a class and a method that implement it:

    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    
    public class MatcherWithExceptions {
      private string m_searchStr;
      private Regex m_searchRegex;
      private IEnumerable m_exceptionRegexes;
    
      public string SearchString {
        get { return m_searchStr; }
        set {
          m_searchStr = value;
          m_searchRegex = new Regex(value);
        }
      }
    
      public string[] ExceptionStrings {
        set { m_exceptionRegexes = from es in value select new Regex(es); }
      }
    
      public bool IsMatch(string testStr) {
        return (
          m_searchRegex.IsMatch(testStr)
          && !m_exceptionRegexes.Any(er => er.IsMatch(testStr))
        );
      }
    }
    
    public class App {
      public static void Main() {
        var mwe = new MatcherWithExceptions();
    
        // Set up the matcher object.
        mwe.SearchString = @"\b\d{5}\b";
        mwe.ExceptionStrings = new string[] {
          @"\.$"
        , @"\(.*" + mwe.SearchString + @".*\)"
        , @"if\(.*" + mwe.SearchString + @".*//endif"
        };
    
        var testStrs = new string[] {
          "1." // False
        , "11111." // False
        , "(11111)" // False
        , "if(11111//endif" // False
        , "if(11111" // True
        , "11111" // True
        };
    
        // Perform the tests.
        foreach (var ts in testStrs) {
          System.Console.WriteLine(mwe.IsMatch(ts));
        }
      }
    }
    

    So above, we set up the search string (the five digits), multiple exception strings (your s1, s2 and s3), and then try to match against several test strings. The printed results should be as shown in the comments next to each test string.

提交回复
热议问题