perl 如何确定模式在字符串中匹配的位置?

3gtaxfhh  于 2022-12-19  发布在  Perl
关注(0)|答案(2)|浏览(162)

我想匹配/vX.X.X/的模式,其中X是数字。例如:/v1.1.1//v1.0.300/。在匹配模式之后,如何才能获得在字符串中找到模式的位置?

nimxete2

nimxete21#

@-包含找到匹配和捕获的偏移量。

  • $-[0]是模式匹配的偏移。
  • $-[1]是第一次捕获匹配时的偏移。
  • $-[2]是第二次捕获匹配时的偏移。
  • 等等。

因此,您可以使用以下命令:

if ( $s =~ m{/v\d+\.\d+\.\d+/}a ) {
   say "Matched at position $-[0]";
}
vmjh9lq9

vmjh9lq92#

你所采取的方法取决于你想要达到的目标和围绕问题的其他因素。既然你还没有对此发表任何意见,这里就有一个不同想法的散弹。并非所有的想法都适合你正在做的事情。
@-特殊变量具有匹配组起始位置的偏移量。第一个元素是整个匹配的起始位置,第二个元素(索引1)是$1匹配的起始位置,依此类推。如果模式是所需的整个字符串,则可以使用该数组中的第一个元素:

if( $string =~ /\bv\d+\.\d+\.\d+\b/ ) {
    my $position = $-[0];
    say "Position is $position";
    }

如果你的模式周围有其他东西,而你想要的东西在第一个匹配组中,你可以使用第二个元素(记住,匹配组是按照左括号的顺序编号的):

if( $string =~ /before (v\d+\.\d+\.\d+) after/ ) {
    my $position = $-[1];
    say "Position is $position";
    }

当您的模式更改时,您可能需要使用您使用的元素进行更新。
还有@+,工作原理相同,但有结束位置。我在Mastering Perl第一版中有很多这样的例子。我把它留到那本书中,因为我发现很多人搞不清哪个元素对应于模式的哪个部分。考虑一下你以后是否会记住这一点。
可以使用index来获取匹配字符串的位置:

if( $string =~ /\b(v\d+\.\d+\.\d+)\b/ ) {
    my $matched = $1;
    my $position = index( $string, $matched );
    say "Position is $position";
    }

使用Perl v5.10中的/p标志和${^PREMATCH}变量,计算字符串匹配部分之前的位置:

use v5.10;

if( $string =~ /\bv\d+\.\d+\.\d+\b/p ) {
    my $position = length ${^PREMATCH};
    say "Position is $position";
    }

在标量上下文中使用/g标志,Perl会记住匹配结束的字符串位置,减去匹配长度,查看匹配开始的位置:

if( $string =~ /\b(v\d+\.\d+\.\d+)\b/g ) {
    my $matched = $1;
    my $position = pos( $string ) - length($1);
    say "Position is $position";
    }

如果每个字符串有多个匹配项,你必须调整这些匹配项。一种方法是使用while循环,因为condition仍然是一个标量上下文:

while( $string =~ /\b(v\d+\.\d+\.\d+)\b/g ) {
    my $matched = $1;
    my $position = pos( $string ) - length($1);
    say "Position is $position";
    }

相关问题