Подтвердить что ты не робот

Perl regex заменить count

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

4b9b3361

Ответ 1

$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 работает циклично, когда вы это делаете. Но не традиционный цикл.

Ответ 2

Вот один из способов. Для этого требуется, чтобы внешний счетчик обновлялся в 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

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

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!

Ответ 3

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