我一直在努力尝试在单个Regex系列中匹配一组相对简单的可能的单词顺序。
基本上,我想匹配这些(在其他语法相似的)可能性:
“设置var on”
“将var设置为关闭”
“set var on”
“set var off”
“设置var”
“设置在var”
“设置在var”
“set off var”
我需要的唯一群组是“ var ”(可以是任何一个单词)和值,它们将始终打开或关闭。这是基本的想法。
考虑到这一点,有两种可能的语法结构:
(on/off) (perhaps a word) (a word)
(a word) (on/off)
我能够使用以下正则表达式独立匹配这些可能性:
/((on |off )([a-z]{1,})? ([a-z]{2,}))/i
/([a-z]{2,}) (on|off)/i
所以,我想我可以这样做:
/(((on |off )([a-z]{1,})? ([a-z]{2,})))|(([a-z]{2,}) (on|off))/i
这只是(短语1)|(短语2),但是短语2总是匹配“set off”,认为“set”是名称。我也尝试过:
/((?!set)) (((on |off )([a-z]{1,})? ([a-z]{2,})))|(([a-z]{2,}) (on|off))/i
没有成功。
编辑1:另外,我忽略了这些短语可以在文件的任何地方找到;他们不是独立的。
例如:“这是设置var 的方式”与“设置var ”的可能性相同
问题:
在没有必要的情况下,我可以一起完成这项工作的最佳方式是什么 分开匹配?
有没有办法强制匹配正则表达式OR语句的订单?
答案 0 :(得分:2)
'the'可能总是出现在'var'之前:
((the)? var)
'set'总是从表达式开始:
^set
'on'和'off'是互斥的,但需要一个:
(on|off)
'var'和'on'/'off'一个接一个地出现,没有特别的顺序。现在一起:
^set ((the)? var (on|off)|(on|off) (the)? var)$
注意:我是.NET开发人员。正则表达式是非常标准的,上面应该可以工作,但可能有更有效的方法在perl中编写它。
答案 1 :(得分:0)
每当您尝试匹配复杂数据时,您应该尝试创建语法。 Perl正则表达式允许您通过(?(DEFINE)...)
指定递归语法。
use strict; use warnings; use feature 'say';
my $grammar = qr(
set \s+ (?:the \s+)? (?<variable>(?&VAR)) \s+ (?:to \s+)? (?<value>(?&VAL))
| set \s+ (?<value>(?&VAL)) \s+ (?:the \s+)? (?<variable>(?&VAR))
(?(DEFINE)
(?<VAL> on | off) # edit only here to add new values
(?<VAR> (?!the|(?&VAL)) \w+)
)
)x; # /x -- whitespace is irrelevant
while(<>){
if (/$grammar/) { say "> val: $+{value} var: $+{variable}" }
else { say "> no match" }
}
要注意的语法:(?&rule)
调用命名规则。名为capture的(?<name>pattern)
允许通过%+
哈希进行访问。也用于在(DEFINE)
块中声明规则。
示例会话:
set the switch to off!
> val: off var: switch
I would like to set something on fire...
> val: on var: something
set on the set!
> val: on var: set
set on the set off something
> val: on var: set
set on off
> no match
请注意,我通过断言变量与值不匹配来使语法明确无误。但是,上面的示例确实显示了一些可能未按预期解析的有趣案例。
有关在正则表达式中编写语法的更强大方法,请查看Regexp::Grammars。