Давайте сделаем шаг назад
$mfgs = "AUDBMWCH-FO-TOY";
while( $mfgs =~ /(.{3})/g ) {
print $1 =~ s/-// . "\n";
}
просто читает строку $mfgs
по три символа за раз и удаляет дефисы.
Можно переписать это следующим образом:
say for map { s|-||r } $mfgs =~ /.../g ; # Works in Perl 5.14+
use List::MoreUtils 'apply';
say for apply { s|-|| } $mfgs =~ /.../g ; # If that 'r' flag isn't there
или используйте оператор транслитерации (tr///
), видя, что по сути ничего не происходит в регулярном выражении:
say for map tr!-!!dr , $mfgs =~ /.../g ;
Оба способа дали бы одинаковые результаты, если в блоке из трех символов имеется только один дефис. Это потому, что tr/-//dr
удалит все дефисы, а s/-//r
удалит только первое вхождение.
Это отвечает, как можно было сделать это иначе, поэтому давайте посмотрим, почему это не сработало раньше
Почему нельзя $1
изменить?
Согласно perldoc perlvar
(выделение добавлено):
$<digits> ($1, $2, ...)
Содержит подшаблон из соответствующего набора захвата
скобки из последнего успешного сопоставления с образцом, не считая
шаблоны сопоставляются во вложенных блоках, которые уже были завершены.
Эти переменные только для чтения и динамически ограничены.
Другими словами, $1
нельзя изменить, это то, что s///
пытался сделать.
Однако, копия $1
может быть изменена, что в некоторой степени рассматривается в решении Джонатана Леффлера .