0

我一直在努力尝试在单个正则表达式行中匹配一组相对简单的可能单词顺序。

基本上,我想匹配这些(以及其他语法相似的)可能性:

“设置变量”

“关闭 var”

“设置变量”

“设置 var 关闭”

“引爆 var”

“设置在 var 上”

“在 var 上设置”

“启动 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:另外,我没有提到这些短语可以在文件的任何地方找到;他们不在独立的路线上。

例如:“ this is the way to set the var on ”与“ set the var on ”一样


问题:

  1. 我可以一起做这件事而不必单独匹配的最好方法是什么?

  2. 有没有办法强制正则表达式 OR 语句匹配顺序?

4

2 回答 2

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 中可能有更有效的方法来编写它。

于 2013-01-15T00:12:40.190 回答
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)调用命名规则。(?<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

于 2013-01-15T00:53:14.807 回答