Я действительно сторонник того, что нет смысла встраивать дополнительную сложность в регулярное выражение, если только в этом нет необходимости (или если вы просто развлекаетесь). В коде, который я на самом деле планировал использовать, я бы оставил его простым, например:
my $string = "one two three four five";
$string =~ m/\w+\s*/g for 1 .. 2;
substr( $string,pos($string) ) =~ s/(\w+)/3/;
print "$string\n";
Использование m//g
в скалярном контексте приводит к тому, что оно совпадает один раз за итерацию цикла for
. На каждой итерации pos()
отслеживает окончание самого последнего подстатья на $string
. После того как вы прошли 'n' итераций (в нашем случае две), вы можете подключить pos()
к substr()
. Используйте substr($string...
в качестве lvalue. Это заставит совпадение регулярного выражения начинаться с любой позиции, которую вы указали во втором аргументе. Мы подключаем туда pos
, что заставляет его брать следующий матч везде, где остановился последний матч.
Этот подход исключает явный счетчик (хотя цикл for, по сути, одно и то же без указания переменной счетчика). Этот подход также масштабируется лучше, чем подход s//condition ? result : result/eg
, потому что он остановится после того, как будет выполнено третье совпадение, вместо того, чтобы продолжать попытки сопоставления, пока не будет достигнут конец потенциально большой строки. Другими словами, подход s///eg
не ограничивает сопоставление, он только условно имеет дело с результатом сколь угодно большого числа успешных совпадений.
В предыдущем вопросе на ту же тему я однажды вставил счетчик в левой части оператора s ///. Хотя это работает для этого конкретного случая, это не идеальное решение, потому что оно склонно к отказу от обратного. Это еще один случай, когда простота была бы лучшим подходом. Я упоминаю об этом здесь, чтобы вы могли избежать соблазна попробовать такую хитрость (если только вы не хотите повеселиться с возвратом).
Подход, который я опубликовал здесь, я считаю, очень ясен; вы смотрите на это и знаете, что происходит: совпадать дважды, отслеживать последнюю позицию матча, теперь сопоставлять в третий раз с заменой. У вас может быть умный, у вас может быть эффективный, и у вас может быть ясный. Но иногда вы не можете иметь все три. Здесь вы получаете эффективный и ясный.