如何在Perl中找到正则表达式匹配的_all_位置?

时间:2017-08-17 09:13:58

标签: regex perl

我可以从this回答,如果我这样做

sub match_all_positions {
    my ($regex, $string) = @_;
    my @ret;
    while ($string =~ /$regex/g) { push @ret, $-[0] }
    return @ret
}

print join ',', match_all_positions('0{3}', '001100010000');

我得到了

4,8

我需要做什么才能使所有的索引匹配,即使重叠时,例如上例中的位置8和9?

我能做到

sub match_all_positions_b  {
    my ($substr, $string) = @_;
    return unless index($string, $substr) > 0;
    my @res;
    my $i = 0;
    while ($i <= (length($string) - $length)) {
        $i = index($string, $substr, $i);
        last if $i < 0;
        push @res, $i++;
    }
    return @res;
}

print join ',', match_all_positions_b('000', '001100010000');

只允许我匹配子字符串,或

sub match_all_positions_c {
    my ($substr, $string) = @_;
    my $re = '^' . $substr;
    my @res;
    for (0..(length($string) - $length)) {
         push @res, $_ if substr($string, $_) =~ /$re/;
    }
    return @res;
}

print join ',', match_all_positions_c('0{3}', '001100010000');

慢两倍。

有没有办法让所有匹配,即使它们重叠?或者我应该只考虑速度损失,因为使用正则表达式匹配是固有的吗?

2 个答案:

答案 0 :(得分:7)

您需要更新zero-width look-ahead匹配的正则表达式。

尝试按照以下方式调用您的函数:

print join ',', match_all_positions('(?=0{3})', '001100010000');

答案 1 :(得分:0)

如果您想找到匹配的位置:

my @matches;
push @matches, "$-[1]:$+[1]" while "aabbcc" =~ /(?=(a.*c))/sg;

输出:

0:6
1:6

如果你想要所有可能的比赛,

local our @matches;
"aabbcc" =~ /(a.*?c)(?{ push @matches, "$-[1]:$+[1]" })(?!)/s;

输出:

0:5
0:6
1:5
1:6