Perl正则表达式替换计数

时间:2011-06-26 05:08:04

标签: regex perl

是否可以指定要替换的最大匹配数。例如,如果在“Hello World”中匹配“l”,是否可以替换前2个l'字符,而不是第3个字符而不循环?

3 个答案:

答案 0 :(得分:9)

这是一种方法。这需要使用(?{code})构造内的(?(condition)true-sub-expression|false-sub-expression)块在RE内更新外部计数器。有关说明,请参阅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!

答案 1 :(得分:9)

$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;

这是一个循环,各种各样,因为当你这样做时,// /// g以循环方式工作。但不是传统的循环。

答案 2 :(得分:0)

简答:不。您需要在某种循环中执行替换。