Сколько замен произошло в Perl s /// g? - PullRequest
10 голосов
/ 23 июня 2010

Маленький пример:

perl -e '$s="aaabbcc";$c=()=$s=~/a/g;print"$c\n$s\n"' (м // г) выходов

3
aaabbcc

, тогда как perl -e '$s="aaabbcc";$c=()=$s=~s/a/x/g;print"$c\n$s\n"' (s /// g) выводит

1
xxxbbcc

Я бы хотел сделать обе вещи одновременно, не сопоставляя сначала: подставить и узнать количество замен. Очевидно, a s /// g не возвращает количество подстановок в скалярном контексте - в отличие от m // g с совпадениями. Это возможно? Если да, то как?

perlre, perlvar и perlop не оказали помощь (или я просто не смог ее найти).

1 Ответ

14 голосов
/ 23 июня 2010

s/// возвращает количество замен, сделанных в скалярном контексте.С perlop (выделение добавлено):

s / PATTERN / REPLACEMENT / msixpogce
Поиск строки для шаблона и, если она найдена, заменаэтот шаблон с текстом замены и возвращает количество выполненных замен .В противном случае он возвращает false (в частности, пустую строку).

Ваша проблема в том, что вы не вызывали s/// в скалярном контексте.Вы вызвали его в контексте списка, а затем оценили присваивание (в пустой список) в скалярном контексте.Присвоение списка в скалярном контексте возвращает количество элементов, созданных правой частью выражения.Поскольку s/// возвращает одно значение (как в списке, так и в скалярном контексте), количество элементов всегда равно единице, даже если s/// ничего не делал.

perl -E "$s='aaabbcc'; $c=()=$s=~s/x/y/g; say qq'$c-$s'"  # prints "1-aaabbcc"

Для вызова s/// вскалярный контекст, пропустите псевдо-оператор =()=.

perl -E "$s='aaabbcc'; $c=$s=~s/a/x/g; say qq'$c-$s'"  # prints "3-xxxbbcc"
...