当然这是可能的。毕竟,我们谈论的是 Perl 正则表达式。但它会相当难看:
say "55336"=~m{(\d)\1(\d)\2(\d)(?(?{$1+1==$3})|(*F))}?"match":"fail";
或印刷精美:
say "55336" =~ m{ (\d)\1 (\d)\2 (\d)
(? (?{$1+1==$3}) # true-branch: nothing
|(*FAIL)
)
}x
? "match" : "fail";
这是做什么的?我们在普通捕获中收集数字。最后,我们使用 if-else 模式:
(? (CONDITION) TRUE | FALSE )
我们可以将代码嵌入到带有(?{ code })
. 此代码的返回值可以用作条件。((*FAIL)
短(*F)
:)动词导致匹配失败。如果(*PRUNE)
您只想要一个分支,而不是整个模式都失败,请使用。
嵌入式代码也非常适合调试。但是,较旧的 perls 不能在此正则表达式代码中使用正则表达式 :-(
所以我们可以匹配很多东西并在模式本身内部测试它的有效性。但是,在模式之外执行此操作可能是一个更好的主意,例如:
"string" =~ /regex/ and (conditions)
现在到您的主要模式N-3N-2N-1NNN+1N+2N+3
(我希望我正确解析它):
my $super_regex = qr{
# N -3 N-2 N-1 N N N+1 N+2 N+3
(\d)-3\1-2\1-1\1\1(\d)(\d)(\d)
(?(?{$1==$2-1 and $1==$3-2 and $1==$4-3})|(*F))
}x;
say "4-34-24-144567" =~ $super_regex ? "match" : "fail";
或者你的意思是
my $super_regex = qr{
#N-3 N-2 N-1 N N N+1 N+2 N+3
(\d)(\d)(\d) (\d)\4 (\d)(\d)(\d)
(? (?{$1==$4-3 and $2==$4-2 and $3==$4-1 and
$5==$4+1 and $6==$4+2 and $7==$4+3})|(*F))
}x;
say "123445678" =~ $super_regex ? "match" : "fail";
可怕的是这些甚至可以工作(使用 perl 5.12)。
我们还可以在匹配时使用构造生成部分模式(??{ code })
——这段代码的返回值被用作模式:
my $super_regex = qr{(\d)(??{$1+1})(??{$1+2})}x;
say "234"=~$super_regex ? "match":"fail"
等等。但是,我认为这种方式的可读性会受到更多影响。
如果您需要超过九个捕获,您可以使用命名捕获与
(?<named>pattern) ... \k<named>
结构体。这些内容也可以在%+
散列中找到,请参阅 perlvar 。
为了进一步深入了解 Perl 正则表达式的秘密,我建议阅读perlre几次。