Perl的正则表达式匹配是贪婪的,所以正则表达式
/\A (a+) (.+) \z/x
匹配字符串'aaab',将设置$ 1 ='aaa'和$ 2 ='b'。 (\ A和\ z只是强制字符串的开头和结尾。)
您还可以提供非贪婪的限定符,如
/\A (a+?) (.+?) \z/x
这仍然匹配,但是给$ 1 ='a'和$ 2 ='aab'。
但我想检查所有可能的方法来生成字符串,这是
$1='aaa' $2='b'
$1='aa' $2='ab'
$1='a' $2='aab'
第一种方式对应于默认的左贪婪行为,第三种方式对应于使第一次匹配非贪婪,但可能存在这些极端之间的方式。是否有一个正则表达式引擎(无论是Perl,还是其他一些如PCRE或RE2)可以尝试所有可能的方法,指定regexp生成给定的字符串?
除此之外,这将允许您实现“POSIX兼容”正则表达式匹配,其中选择最长的总匹配。在我的情况下,我真的希望看到所有可能性。
(一种方法是使用正则表达式本身,在第一次尝试时用+ 1,1}替换+修饰符,然后用{1,2},{1,3}依旧替换 - 对于每个+的组合正则表达式中的*修饰符。这非常费力且缓慢,并且停止时并不明显。我希望能有更聪明的东西。)
要回答Jim G.关于这可能解决的问题的问题,请考虑规则给出的两种语言之间基于规则的翻译系统
translate(any string of one or more 'a' . y) = 'M' . translate(y)
translate('ab') = 'U'
然后有翻译('aaab')的可能结果,即'MU'。 您可以尝试将这些规则放在基于正则表达式的Perl代码中,如
our @m;
my @rules = (
[ qr/\A (a+) (.*) \z/x => sub { 'M' . translate($m[1]) } ],
[ qr/\A ab \z/x => sub { 'U' } ],
);
其中translate遍历每个@rules并尝试依次应用它们:
sub translate {
my $in = shift;
foreach (@rules) {
my ($lhs, $rhs) = @$_;
$in =~ $lhs or next;
local @m = ($1, $2);
my $r = &$rhs;
next if index($r, 'fail') != -1;
return $r;
}
return 'fail';
}
但是,调用translate('aaab')会返回'fail'。这是因为 它尝试应用匹配(a +)(。*)和正则表达式的第一个规则 引擎找到与最长字符串'a'的匹配。
使用ikegami建议的答案,我们可以尝试各种方式 正则表达式生成字符串:
use re 'eval';
sub translate {
my $in = shift;
foreach (@rules) {
my ($lhs, $rhs) = @$_;
local our @matches;
$in =~ /$lhs (?{ push @matches, [ $1, $2 ] }) (*FAIL)/x;
foreach (@matches) {
local @m = @$_;
my $r = &$rhs;
next if index($r, 'fail') != -1;
return $r;
}
}
return 'fail';
}
现在翻译('aaab')返回'MU'。
答案 0 :(得分:4)
local our @matches;
'aaab' =~ /^ (a+) (.+) \z (?{ push @matches, [ $1, $2 ] }) (*FAIL)/x;