Perl регулярное выражение заменить счет - PullRequest
12 голосов
/ 26 июня 2011

Можно ли указать максимальное количество совпадений для замены. Например, если сопоставить 'l' в "Hello World", можно ли заменить первые 2 символа 'l', но не третьи без зацикливания?

Ответы [ 3 ]

9 голосов
/ 26 июня 2011

Вот один из способов. Это требует обновления внешнего счетчика в RE с использованием блока (?{code}) внутри конструкции (?(condition)true-sub-expression|false-sub-expression). См. perldoc perlre для объяснения.

use Modern::Perl;
use re qw/eval/; # Considered experimental.

my $string = 'Hello world!';

my $count = 2;

my $re =    qr/
                (l)
                (?(?{$count--})|(*FAIL))
            /x;

say "Looking for $count instances of 'l' in $string.";
my ( @found ) = $string =~ m/$re/g;
say "Found ", scalar @found, " instances of 'l': @found";

Вывод:

Looking for 2 instances of 'l' in Hello world!
Found 2 instances of 'l': l l

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

use Modern::Perl;
use strict;
use warnings;
use re qw/eval/; # Considered experimental.

my $string = 'Hello world!';

my $count = 2;
my $position = 0;

my $re =    qr/
                (l)(?{$position=pos})
                (?(?{$count--})|(*FAIL))
            /x;

while( $string =~ m/$re/g ) {
    say "Found $1 at ", $position;
}

И на этот раз вывод:

Found l at 3
Found l at 4

Не думаю, что я бы порекомендовал что-либо из этого. Если бы я думал об ограничении совпадений только одной частью строки, я бы сопоставил ее с substr() строки. Но если вам нравится жить на краю, продолжайте и повеселитесь с этим фрагментом.

Вот оно в подстановке:

use Modern::Perl;
use strict;
use warnings;
use re qw/eval/; # Considered experimental.

my $string = 'Hello world!';
say "Before substitution $string";
my $count = 2;
my $re =    qr/
                (l)
                (?(?{$count--})|(*FAIL))
            /x;

 $string =~ s/$re/L/g;

 say "After substitution  $string";

И вывод:

Before substitution Hello world!
After substitution  HeLLo world!
9 голосов
/ 26 июня 2011
$str = "Hello world!";
$str =~ s/l/r/ for (1,2);
print $str;

Я не понимаю, что плохого в цикле.

Собственно, вот способ:

$str="Hello world!"; 
$str =~ s/l/$i++ >= 2 ? "l": "r"/eg; 
print $str;

Это своего рода цикл, поскольку s /// g работает циклично, когда вы делаете это.Но не традиционный цикл.

0 голосов
/ 26 июня 2011

Краткий ответ: нет. Вам нужно будет выполнить подстановки в каком-то цикле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...