Perl регулярное выражение: как узнать количество совпадений - PullRequest
1 голос
/ 31 августа 2010

Я перебираю серию регулярных выражений и сопоставляю их со строками в файле, например:

for my $regex (@{$regexs_ref}) {
    LINE: for (@rawfile) {
        /@$regex/ && do {
            # do something here
            next LINE;
        };
    }
}

Есть ли способ узнать, сколько у меня совпадений (чтобы я мог обработать их соответственно ...)?

Если нет, то, возможно, это неправильный подход ..? Конечно, вместо прохождения каждого регулярного выражения, я мог бы просто написать один рецепт для каждого регулярного выражения. Но я не знаю, какова лучшая практика?

Ответы [ 4 ]

2 голосов
/ 08 сентября 2014

Как насчет кода ниже:

my $string = "12345yx67hjui89";    
my $count = () = $string =~ /\d/g;
print "$count\n";

Здесь печатается 9, как и ожидалось.

2 голосов
/ 31 августа 2010

Вам нужно будет следить за этим самостоятельно. Вот один из способов сделать это:

#!/usr/bin/perl

use strict;
use warnings;

my @regexes = (
    qr/b/,
    qr/a/,
    qr/foo/,
    qr/quux/,
);

my %matches = map { $_ => 0 } @regexes;
while (my $line = <DATA>) {
    for my $regex (@regexes) {
        next unless $line =~ /$regex/;
        $matches{$regex}++;
    }
}

for my $regex (@regexes) {
    print "$regex matched $matches{$regex} times\n";
}

__DATA__
foo
bar
baz
2 голосов
/ 31 августа 2010

При обработке CA :: Parser , связанной со совпадениями для /$CA::Regex::Parser{Kills}{all}/, вы используете перехваты $1 вплоть до $10, и большинство остальных использует меньше. Если под числом совпадений вы подразумеваете количество захватов (самое большое n , для которого $n имеет значение), вы можете использовать специальный массив Perl @- (выделение добавлено):

@ LAST_MATCH_START

@ -

$-[0] - смещение начала последнего успешного матча. $-[n] - это смещение начала подстроки, совпадающее с n -ым подшаблоном или undef, если подшаблон не совпадает. Таким образом, после матча с $_, $& совпадает с substr $_, $-[0], $+[0] - $-[0]. Точно так же $n совпадает с

substr $_, $-[n], $+[n] - $-[n]

, если определено $-[n] и $+ совпадает с

substr $_, $-[$#-], $+[$#-] - $-[$#-]

Можно использовать $#-, чтобы найти последнюю найденную подгруппу в последнем удачном совпадении. Сравните с $#+, количеством подгрупп в регулярном выражении. Сравните с @+.

Этот массив содержит смещения начала последних успешных субматч в текущей активной динамической области. $-[0] - смещение в строку начала всего матча. n -й элемент этого массива содержит смещение n-го субматча, поэтому $-[1] - это смещение, с которого начинается $1, $-[2] смещение, с которого начинается $2, и так далее.

После совпадения с некоторой переменной $var:

  • $ `совпадает с substr($var, 0, $-[0])
  • $& совпадает с substr($var, $-[0], $+[0] - $-[0])
  • $' совпадает с substr($var, $+[0])
  • $1 совпадает с substr($var, $-[1], $+[1] - $-[1])
  • $2 совпадает с substr($var, $-[2], $+[2] - $-[2])
  • $3 совпадает с substr($var, $-[3], $+[3] - $-[3])

Пример использования:

#! /usr/bin/perl

use warnings;
use strict;

my @patterns = (
  qr/(foo(bar(baz)))/,
  qr/(quux)/,
);

chomp(my @rawfile = <DATA>);

foreach my $pattern (@patterns) {
  LINE: for (@rawfile) {
    /$pattern/ && do {
      my $captures = $#-;
      my $s = $captures == 1 ? "" : "s";
      print "$_: got $captures capture$s\n"; 
    };
  }
}

__DATA__
quux quux quux
foobarbaz

Выход:

foobarbaz: got 3 captures
quux quux quux: got 1 capture
2 голосов
/ 31 августа 2010

Если вы выполняете сопоставление в контексте списка (т. Е. Присваиваете списку), вы получаете все совпадения и группировки в списке. Затем вы можете просто использовать этот список в скалярном контексте, чтобы получить количество совпадений.

Или я неправильно понял вопрос?

Пример:

my @list = /$my_regex/g;
if (@list)
{
  # do stuff
  print "Number of matches: " . scalar @list . "\n";
}
...