【问题标题】:How to Tell Regex to Check Whole Sub-String?如何告诉正则表达式检查整个子字符串?
【发布时间】:2013-12-04 03:17:24
【问题描述】:

首先是我正在使用的正则表达式:

       String pattern = @"Create(\s+)Table(\s+)(\([a-z0-9]+\))(\s+)Columns(\s+)((\(([a-z0-9]+);(INTEGER|DECIMAL|STRING);(\d{1,3});(((YES|NO);){3})([a-z0-9]+)\))+)";
        Match CMD = Regex.Match(Command, pattern, RegexOptions.IgnoreCase);

        if (CMD.Success)
        {
            return true;
        }

此正则表达式对以下模式按预期工作:

1) 创建表 (MARKS) 列(fountains;StriNg;999;NO;YES;NO;wicked)(rivers;String;500;NO;YES;NO;sweet)

2) 创建表 (MARKS) 列 (ID;Integer;4;YES;YES;YES;0) (riversString;50;NO;YES;NO;sweet)

在第一个模式中,整个字符串是匹配的,但在第二个模式中,只有子字符串 创建表 (MARKS) 列 (ID;Integer;42;YES;YES;YES;0) 匹配

现在它为以下模式返回 false false:

3)创建表 (MARKS) 列 (IDInteger;42;YES;YES;YES;0) (rivers;String;500;NO;YES;NO;sweet)

第二个模式和第三个模式有相同的错误,但唯一的区别是在第二个模式中匹配 \(([a-z0-9]+);(INTEGER|DECIMAL|STRING) ;(\d{1,3});(((YES|NO);){3})([a-z0-9]+)\) 在字符串结尾之前已经出现并且因此正则表达式返回 true。

现在我的问题是如何告诉拒绝继续匹配直到字符串结尾?

所以基本上是这样的:不是或除了加号(这意味着一个或多个匹配prevoius)我想要=>一个或多个匹配直到行尾。这样,第三个将导致子字符串 Create Table (MARKS) Columns (rivers;String;500;NO;YES;NO;sweet) 来自 Create Table (MARKS) Columns (IDInteger ;42;YES;YES;YES;0) (rivers;String;500;NO;YES;NO;sweet)

【问题讨论】:

    标签: c# regex c#-4.0


    【解决方案1】:

    使用开始 (^) 和结束 ($) 符号,例如:

    String patter = @"^\d+$";
    

    【讨论】:

    • 是的,我知道这些符号,但只是将它们放在开头或结尾仍然会为第三个模式返回 false?
    • 那么这是主模式的问题,而不是线条边框
    • 是的,主要模式存在问题,这就是为什么要寻求帮助?我尽力解释了这一点
    【解决方案2】:

    \s*? 放在Columns(...) 组的右括号之后,以匹配两个Columns 组之间的0+(惰性)空格:

    Create(\s+)Table(\s+)(\([a-z0-9]+\))(\s+)Columns(\s+)((\(([a-z0-9]+);(INTEGER|DECIMAL|STRING);(\d{1,3});(((YES|NO);){3})([a-z0-9]+)\)\s*?)+)
    

    最后一个字符串不匹配,因为您忘记了 ID 和整数之间的 ;

    编辑:

    好的,我明白你需要什么了。

    这匹配 Columns 组之间的 0+ 个空格并继续搜索直到找到有效组

    Create(\s+)Table(\s+)(\([a-z0-9]+\))(\s+)Columns(\s*\([^)]*\))*(\s*\(([a-z0-9]+);(INTEGER|DECIMAL|STRING);(\d{1,3});(((YES|NO);){3})([a-z0-9]+)\))+
    

    查看 RegEx101 http://regex101.com/r/rU6eJ4

    编辑 2:

    这个只匹配同一行的字符串:

    Create[^\S\n]+Table[^\S\n]+(\([a-z0-9]+\))[^\S\n]+Columns([^\S\n]*\([^)]*\))*([^\S\n]*\(([a-z0-9]+);(INTEGER|DECIMAL|STRING);(\d{1,3});(((YES|NO);){3})([a-z0-9]+)\))+
    

    【讨论】:

    • 是的,我是故意这样做的....但是子字符串“创建表(标记)列(河流;字符串;500;否;是;否;甜)”与模式匹配,但因为“ (IDInteger;42;YES;YES;YES;0)" 在 "(rivers;String;500;NO;YES;NO;sweet)" 前面,它返回 false,但我希望这种模式(模式 3)为真
    • 所以你需要在第一个;上指定?修饰符
    • 我明白你的意思,我重构了我的代码并完全改变了我的正则表达式......请参阅我的答案。谢谢
    • @FabioDelarias 我还添加了一个只匹配同一行上的字符串的编辑(\s 也匹配换行符)。
    【解决方案3】:

    不要只使用开始 (^) 和结束 ($) 符号,使用全局修饰符可能会解决这个特定问题。

    字符串模式 = @"/^\d+$/g";

    【讨论】:

      【解决方案4】:

      好的,所以基本上我决定将我的正则表达式分解为两个正则表达式:

              String pattern = @"Create(\s+)Table(\s+)(\([a-z0-9]+\))(\s+)Columns(\s+)(((\([a-z0-9;]+\))\s*)+)";
              Match CMD = Regex.Match(Command, pattern, RegexOptions.IgnoreCase);
      
              if (CMD.Success)
              {
                  String SubCommand = CMD.Groups[6].Value;
                  String SubPattern = @"\(([a-z0-9]+);(INTEGER|DECIMAL|STRING);(\d{1,3});(YES|NO);(YES|NO);(YES|NO);([a-z0-9]+)\)";
                  MatchCollection match = Regex.Matches(SubCommand, SubPattern, RegexOptions.IgnoreCase);
      
                 if (match.Count != 0)
                  {
                      return true;
                  }
              }
      

      我认为没有很好地解释我的问题,但我感谢大家的帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-26
        • 1970-01-01
        相关资源
        最近更新 更多