Сколько подстановок произошло в Perl s///g?

Небольшой пример:

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

3
aaabbcc

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

1
xxxbbcc

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

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

Ответ 1

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

s/PATTERN/ЗАМЕНА/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"