我需要将字符串与预定义关键字列表进行匹配,并将其捕获到一个组中,因为关键字前面可能有一个可选字符。
允许的关键字:
可选字符:!
- 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+)\)
我可以成功捕获群组(action
,field
,value
),但正则表达式只允许startswith
的可选字符。如何分离这两个规则并仍然捕获完整的关键字?像capture=(optional ?)(any of the allowed keywords)
答案 0 :(得分:0)
只需将!?
放在捕获组之外。
@"!?\b(?<action>startswith|endswith|contains|equals)\((?<field>\w+),(?<value>\w+)\)"
\b
之后的!?
字边界是非常需要的。
答案 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)
\)