Как ограничить найденные совпадения на Perl с помощью регулярных выражений? - PullRequest
7 голосов
/ 11 ноября 2011

Я прихожу просить вашей помощи после многих исследований по этому вопросу:

Я пытаюсь ограничить повторение замен, которые регулярное выражение Perl делает для большого текста.Я искал в Google и обнаружил, что формат {2,3} (мин., Макс.), Однако, похоже, это другой способ использования синтаксиса, который я использую.

$replaced=~s/$var/$var2/g; # replaces all ocurrences
$replaced=~s/$var/$var2/;  # replaces only first one

my nonоптимальное решение:

for($i=0; $i<8; $i++){

    $replaced=~s/$var/$var2/;
}

Что я пробовал:

$replaced=~s/$var/$var2/{8};
$replaced=~s/$var/$var2{8}/;

Любая помощь будет оценена!

edit: ОК, так что в значительной степени должен быть циклучаствую да .. разве не странно, что нет встроенного параметра для его ограничения ??

Ответы [ 3 ]

7 голосов
/ 11 ноября 2011

Ответы с \G, вероятно, являются наиболее практичным способом сделать то, что вы хотите, но просто для удовольствия или для назидания или чего-то еще, вот другой способ (требующий Perl 5.10 или выше), используя утверждения кода и возвратные глаголы управления (*COMMIT) и (*FAIL):

my $str = "Bananas in pajamas are coming down the stairs";
my $limit = 3;
my $count;

$str =~ s/(*COMMIT)(?(?{ $count++ >= 3 })(*FAIL))a/A/g;
say $str;

, которые оставляют текст "BAnAnAs в пижамах спускаются по лестнице" в $str - только первые три "a" sбыли затронуты, и он останавливает сканирование строки для других совпадений после третьего.

4 голосов
/ 11 ноября 2011

Я не бегло говорю на Perl, но я полагаю, что вы хотите использовать "\G Assertion" ( подробнее здесь ), который продолжит поиск нового совпадения на месте предыдущегосовпадение прервано:

for($i=0; $i<8; $i++){

    $replaced=~s/\G$var/$var2/;
}

Я не уверен, действительно ли это более эффективно, но, похоже, именно для этого оно и предназначено ...

1 голос
/ 11 ноября 2011

Ответ: http://codenode.com/2010/06/24/single-pass-replace-with-perl-regex-g-anchor/

Выдержка с модификацией для счетчика:

my $cnt = 0;
if ( $query =~ m/\bORDER BY /gi ) {
   while ($query =~ s/\G(.+?)\s+ASC/$1/gmsi && pos $query) {
       $cnt++; last if $cnt >= 8;
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...