单独的正则表达式条款

时间:2015-03-11 15:28:15

标签: c# .net regex pattern-matching

我需要将字符串与预定义关键字列表进行匹配,并将其捕获到一个组中,因为关键字前面可能有一个可选字符。

实施例

允许的关键字:

  • 包含
  • startswith
  • 等于
  • 的endsWith

可选字符:!

- input value              - comment
contains(field,value)      // OK
startswith(field,value)    // OK
test(field,value)          // NOK (test is not a valid keyword)
equals(field,value)        // OK
!startswith(field,value)   // OK  (optional character ! allowed)
!contains(field,value)     // OK  (optional character ! allowed)

正则表达式

我尝试使用以下正则表达式:

(?<action>!?startswith|endswith|contains|equals)\((?<field>\w+),(?<value>\w+)\)

我可以成功捕获群组(actionfieldvalue),但正则表达式只允许startswith的可选字符。如何分离这两个规则并仍然捕获完整的关键字?像capture=(optional ?)(any of the allowed keywords)

这样的东西

4 个答案:

答案 0 :(得分:0)

只需将!?放在捕获组之外。

@"!?\b(?<action>startswith|endswith|contains|equals)\((?<field>\w+),(?<value>\w+)\)"
\b之后的!?字边界是非常需要的。

DEMO

答案 1 :(得分:0)

如果你想捕捉!startswith和!contains,请使用以下内容......

(?<action>!?(startswith|endswith|contains|equals))\((?<field>\w+),(?<value>\w+)\)

答案 2 :(得分:0)

为什么不使用

(?<=^|\p{P}|\p{Zs}|\b)(?<action>\!?(?:startswith|endswith|contains|equals))\((?<field>\w+),(?<value>\w+)\)(?=$|\p{P}|\p{Zs}|\b)

您将匹配几乎所有可能的界限+&#34;!?&#34;仅在?<action>组中使用一次,您的操作将使用或不包含!符号来保存方法名称。

以下是一些测试代码:

var MyRegex = new Regex(
      "(?<=^|\\p{P}|\\p{Zs}|\\b)(?<action>\\!?(?:startswith|endswit" +
      "h|contains|equals))\\((?<field>\\w+),(?<value>\\w+)\\)(?=$|\\p" +
      "{P}|\\p{Zs}|\\b)",
    RegexOptions.IgnoreCase
    | RegexOptions.Multiline
    | RegexOptions.CultureInvariant
    | RegexOptions.Compiled
    );
// Capture all Matches in the InputText
var ms = MyRegex.Matches(@"contains(field,value)    OK
startswith(field,value)  OK
test(field,value)        NOK (test is not a valid keyword)
equals(field,value)      OK
!startswith(field,value) OK  (optional character ! allowed)
!contains(field,value)   OK  (optional character ! allowed)");

foreach (var capturedgroup in ms.Cast<Match>().ToList())
{
    var action = capturedgroup.Groups["action"].Value;
    var field = capturedgroup.Groups["field"].Value;
    var value = capturedgroup.Groups["value"].Value;
}

或者,如果您必须将方法名称检查为单独的字符串,请使用:

var MyRegex = new Regex("(?<action>\\!?(?:startswith|endswith|contains|equals))\\((?<field>\\w+),(?<value>\\w+)\\)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
var ms = MyRegex.Match(@"!contains(field,value)");
var action = ms.Groups["action"].Value;
var field = ms.Groups["field"].Value;
var value = ms.Groups["value"].Value;

答案 3 :(得分:0)

这是另一个。普遍的想法是将!?移到父母之外。

@"(?<!\S)(?<action>!?(?:startswith|endswith|contains|equals))\((?<field>\w+),(?<value>\w+)\)"

格式化

 (?<! \S )
 (?<action>                    #_(1 start)         
      !?
      (?:
           startswith
        |  endswith
        |  contains
        |  equals 
      )
 )                             #_(1 end)         
 \(
 (?<field> \w+ )               #_(2)         
 ,
 (?<value> \w+ )               #_(3)         
 \)