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

时间:2020-03-05 18:59:58  来源:igfitidea点击:

我需要编写一个接收字符串和正则表达式的函数。我需要检查是否存在匹配项,并返回匹配项的开始和结束位置。 (正则表达式已由qr //编译。)

该函数可能还会收到"全局"标志,然后我需要返回所有匹配项的(开始,结束)对。

我不能更改正则表达式,甚至不能在其周围添加"()",因为用户可能会使用"()"和" \ 1"。也许我可以使用(?:)

示例:给定" ababab"和正则表达式" qr / ab /",在全局情况下,我需要取回3对(开始,结束)。

解决方案

回答

pos函数为我们提供比赛的位置。如果将正则表达式放在括号中,则可以使用" length $ 1"来获取长度(从而得出结尾)。像这样

sub match_positions {
    my ($regex, $string) = @_;
    return if not $string =~ /($regex)/;
    return (pos($string), pos($string) + length );
}
sub all_match_positions {
    my ($regex, $string) = @_;
    my @ret;
    while ($string =~ /($regex)/g) {
        push @ret, [pos($string), pos($string) + length ];
    }
    return @ret
}

回答

如果我们希望程序中所有RE的执行速度较慢,也可以使用不推荐使用的$`变量。从perlvar:

$‘      The string preceding whatever was matched by the last successful pattern match (not
           counting any matches hidden within a BLOCK or eval enclosed by the current BLOCK).
           (Mnemonic: "`" often precedes a quoted string.)  This variable is read-only.

           The use of this variable anywhere in a program imposes a considerable performance penalty
           on all regular expression matches.  See "BUGS".

回答

忘记我以前的帖子,我有一个更好的主意。

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

该技术不会以任何方式更改正则表达式。

编辑添加:引用perlvar上的$ 1 .. $ 9. "这些变量都是只读的,并且动态地作用于当前的块。"换句话说,如果要使用$ 1 .. $ 9,则不能使用子例程进行匹配。

回答

内置变量@ -@ +分别保存最后一次成功匹配的开始和结束位置。 $-[0]和$ + [0]对应于整个模式,而$-[N]和$ + [N]对应于$ N($ 1$ 2等)子匹配。