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'
然后有一个translate('aaab')的可能结果,即'MU'。您可以尝试将这些规则基于正则表达式放入Perl代码中,例如
our @m;
my @rules = (
[ qr/\A (a+) (.*) \z/x => sub { 'M' . translate($m[1]) } ],
[ qr/\A ab \z/x => sub { 'U' } ],
);
在每个@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'。
local our @matches;
'aaab' =~ /^ (a+) (.+) \z (?{ push @matches, [ $1, $2 ] }) (*FAIL)/x;
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句