Regex Perl指定字符串中正则表达式的所有匹配项
Perl的regexp匹配是贪婪的,因此Regex Perl指定字符串中正则表达式的所有匹配项,regex,perl,posix,capture,greedy,Regex,Perl,Posix,Capture,Greedy,Perl的regexp匹配是贪婪的,因此 /\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' 第一种方法对应于默认的左贪婪行为,第
/\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'
第一种方法对应于默认的左贪婪行为,第三种方法对应于使第一个匹配非贪婪,但在这些极端之间可能有一些方法。是否有一个regexp引擎(无论是Perl引擎,还是其他一些引擎,如PCRE或RE2),可以让它尝试指定的regexp生成给定字符串的所有可能方法
除此之外,这将允许您实现“POSIX兼容”regexp匹配,其中选择最长的总匹配。就我而言,我真的希望看到所有的可能性
(一种方法是使用正则表达式本身,在第一次尝试时用{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'。
您可以尝试将这些规则放入基于regexp的Perl代码中,如下所示
our @m;
my @rules = (
[ qr/\A (a+) (.*) \z/x => sub { 'M' . translate($m[1]) } ],
[ qr/\A ab \z/x => sub { 'U' } ],
);
其中,translate运行在每个@规则上,并尝试依次应用它们:
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+)(*)和regexp
引擎找到可能最长的字符串“a”的匹配项
使用池上建议的答案,我们可以尝试各种方法
正则表达式生成字符串:
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';
}
现在translate('aaab')返回'MU'。您想解决什么问题?一点也不清楚。您通常无法访问regex引擎试图匹配的所有不同字符串,而且您的问题听起来根本不像正则表达式的匹配(双关语)。正则表达式匹配返回最后一组匹配项和组。如果您想返回所有可能的匹配项,您需要一个不同的接口,并且这种可能性可能会呈指数级增长。你可能需要破解一个正则表达式引擎实现才能得到你想要的结果。谢谢你的关注。我已经编辑了这个问题来展示一个可能的用例。你想解决什么问题?一点也不清楚。您通常无法访问regex引擎试图匹配的所有不同字符串,而且您的问题听起来根本不像正则表达式的匹配(双关语)。正则表达式匹配返回最后一组匹配项和组。如果您想返回所有可能的匹配项,您需要一个不同的接口,并且这种可能性可能会呈指数级增长。你可能需要破解一个正则表达式引擎实现才能得到你想要的结果。谢谢你的关注。我已经编辑了这个问题以显示一个可能的用例。
local our @matches;
'aaab' =~ /^ (a+) (.+) \z (?{ push @matches, [ $1, $2 ] }) (*FAIL)/x;