Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Perl指定字符串中正则表达式的所有匹配项_Regex_Perl_Posix_Capture_Greedy - Fatal编程技术网

Regex Perl指定字符串中正则表达式的所有匹配项

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' 第一种方法对应于默认的左贪婪行为,第

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'
第一种方法对应于默认的左贪婪行为,第三种方法对应于使第一个匹配非贪婪,但在这些极端之间可能有一些方法。是否有一个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;