Предположим, что у меня есть:
my $string = "one.two.three.four";
Как мне играть с контекстом, чтобы получить количество раз, когда шаблон нашел совпадение (3)? Можно ли это сделать с помощью одного слоя?
Я пробовал это:
my ($number) = scalar($string=~/\./gi);
Я думал, что, поставив круглые скобки вокруг $number
, я бы принудительно использовал контекст массива, и с помощью scalar
я получил бы счет. Однако все, что я получаю, это 1
.
Это ставит само регулярное выражение в скалярном контексте, который не является тем, что вы хотите. Вместо этого поместите регулярное выражение в контекст списка (чтобы получить количество совпадений) и поместите его в скалярный контекст.
my $number = () = $string =~ /\./gi;
Я думаю, что самым ясным способом описать это было бы избегать скачкообразного преобразования. Сначала назначьте массив, а затем используйте этот массив в скалярном контексте. Это в основном то, что будет делать идиома = () =
, но без (редко используемой) идиомы:
my $string = "one.two.three.four";
my @count = $string =~ /\./g;
print scalar @count;
@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;
Является ли следующий код однострочным?
print $string =~ s/\./\./g;
Попробуйте следующее:
my $string = "one.two.three.four";
my ($number) = scalar( @{[ $string=~/\./gi ]} );
Он возвращает 3
для меня. Создавая ссылку на массив, регулярное выражение оценивается в контексте списка, а @{..}
отменяет ссылки на ссылку массива.
Метод Фридо: $a = () = $b =~ $c
.
Но это можно упростить еще до простого ($a) = $b =~ $c
, например:
my ($matchcount) = $text =~ s/$findregex/ /gi;
другой способ,
my $string = "one.two.three.four";
@s = split /\./,$string;
print scalar @s - 1;