-1

我的意思是:

例如,a{3,}将贪婪地匹配 'a' 至少 3 次。它可能会找到 5 次、10 次等。我需要这个数字。我需要这个号码作为其余代码。

我可以在不知情的情况下完成其余的工作,但我想也许 Perl 有一些内置变量来给出这个数字,或者有什么技巧可以得到它?

4

4 回答 4

2

只需捕获并使用length.

if (/(a{3,})/) {
   print length($1), "\n";
}
于 2013-06-26T10:40:20.360 回答
2

使用@LAST_MATCH_END 和@LAST_MATCH_START

my $str = 'jlkjmkaaaaaamlmk';
$str =~ /a{3,}/;
say $+[0]-$-[0];

输出:

6

注意:这仅适用于单字符模式。

于 2013-06-26T10:04:12.490 回答
0

Here's an idea (maybe this is what you already had?) assuming the pattern you're interested in counting has multiple characters and variable length:

  • capture the substring which matches the pattern{3,} subpattern
  • then match the captured substring globally against pattern (note the absence of the quantifier), and force a list context on =~ to get the number of matches.

Here's a sample code to illustrate this (where $patt is the subpattern you're interested in counting)

my $str = "some catbratmatrattatblat thing";
my $patt = qr/b?.at/; 

if ($str =~ /some ((?:$patt){3,}) thing/) {
    my $count = () = $1 =~ /$patt/g;
    print $count;
    ...
}

Another (admittedly somewhat trivial) example with 2 subpatterns

my $str = "some catbratmatrattatblat thing 11,33,446,70900,";
my $patt1 = qr/b?.at/; 
my $patt2 = qr/\d+,/;

if ($str =~ /some ((?:$patt1){3,}) thing ((?:$patt2){2,})/) {
    my ($substr1, $substr2) = ($1, $2);
    my $count1 = () = $substr1 =~ /$patt1/g;
    my $count2 = () = $substr2 =~ /$patt2/g;
    say "count1: " . $count1;
    say "count2: " . $count2;
}

Limitation(s) of this approach:

Fails miserably with lookarounds. See amon's example.

于 2013-06-26T10:47:04.793 回答
0

如果您有一个AB/AB{n,}/是复杂模式的模式,我们可以将正则表达式拆分为多个部分:

my $string = "ABABBBB";
my $n = 3;

my $count = 0;
TRY:
while ($string =~ /A/gc) {
  my $pos = pos $string; # remember position for manual backtracking
  $count++ while $string =~ /\GB/g;
  if ($count < $n) {
    $count = 0;
    pos($string) = $pos; # restore previous position
  } else {
    last TRY;
  }
}
say $count;

输出:4

但是,将代码嵌入到正则表达式中进行计数可能更可取,因为它更通用:

my $string = "ABABBBB";
my $count;
$string =~ /A(?{ $count = 0 })(?:B(?{ $count++ })){3,}/ and say $count;

输出:4

缺点是这段代码不能在旧的 perls 上运行。(代码在 v14 和 v16 上进行了测试)。


编辑:如果B模式回溯,第一个解决方案将失败,例如$B = qr/BB?/. 该模式应该匹配ABABBBB字符串 3 次,但该策略只会让它匹配 2 次。使用嵌入式代码的解决方案允许适当的回溯。

于 2013-06-26T10:02:26.013 回答