Есть ярлык на Perl для подсчета количества совпадений в строке?
Предположим, у меня есть:
my $string = "one.two.three.four";
как я должен играть с контекстом, чтобы получить число раз картина матча (3)? Можно ли это сделать с помощью одного вкладыша?
Я попытался это:
my ($number) = scalar($string=~/./gi);
Я думал, что поставив скобки $number
, Я бы принудительно контекст массива, и с помощью scalar
, Я бы получил счет. Однако, все, что я получаю это 1
.
8 ответов:
это помещает само регулярное выражение в скалярный контекст, что не то, что вы хотите. Вместо этого поместите регулярное выражение в контекст списка (чтобы получить количество совпадений) и поместите это в скалярном контексте.
my $number = () = $string =~ /\./gi;
Я думаю, что самым ясным способом описать это было бы избежать мгновенного приведения к скаляру. Сначала назначьте массив, а затем используйте этот массив в скалярном контексте. Основно
= () =
идиома подойдет, но без (редко используемой) идиомы:my $string = "one.two.three.four"; my @count = $string =~ /\./g; print scalar @count;
кроме того, см. Perlfaq4:
есть несколько способов, с разной эффективностью. Если вы хотите, чтобы количество определенного одного символа (X) в строке, вы можете использовать функцию tr/// следующим образом:
$string = "ThisXlineXhasXsomeXx'sXinXit"; $count = ($string =~ tr/X//); print "There are $count X characters in the string";
Это нормально, если вы просто ищете один персонаж. Однако, если вы пытаетесь подсчитать несколько символьных подстрок в более крупной строке, tr/ / / не будет работать. Что вы можете сделать, это обернуть цикл while () вокруг глобального совпадение рисунка. Например, посчитаем отрицательные целые числа:
$string = "-9 55 48 -2 23 -76 4 14 -44"; while ($string =~ /-\d+/g) { $count++ } print "There are $count negative numbers in the string";
другая версия использует глобальное совпадение в контексте списка, затем присваивает результат скаляру, производя подсчет количества совпадений.
$count = () = $string =~ /-\d+/g;
попробуйте это:
my $string = "one.two.three.four"; my ($number) = scalar( @{[ $string=~/\./gi ]} );
возвращает
3
для меня. При создании ссылки на массив регулярное выражение вычисляется в контексте списка и@{..}
де-ссылки на ссылку массива.
my $count = 0; my $pos = -1; while (($pos = index($string, $match, $pos+1)) > -1) { $count++; }
проверено с бенчмарком, это довольно быстро
метод Фридо:
$a = () = $b =~ $c
.но это можно упростить еще больше, чтобы просто
($a) = $b =~ $c
, например :my ($matchcount) = $text =~ s/$findregex/ /gi;
вы могли бы поблагодарить просто обернуть это в функцию,
getMatchCount()
, и не беспокойтесь об этом, уничтожая переданную строку.С другой стороны, вы можете добавить в своп, который может быть немного больше вычислений, но не привести к изменению строки.
my ($matchcount) = $text =~ s/($findregex)//gi;