如何匹配两个实例并使用perl中的正则表达式替换第一个实例?

问题描述:

如果返回两个匹配项,我只想替换第一个实例。如何匹配两个实例并使用perl中的正则表达式替换第一个实例?

例如:

$sen = "The quick brown fox jump over the lazy dog, fox is quick"; 

我怎么能只匹配第一狐狸与狼,反之亦然更换。

输出:

The quick brown wolf jump over the lazy dog, fox is quick 

或:

The quick brown fox jump over the lazy dog, wolf is quick 

感谢。

+0

我一直和你在一起“反之亦然”。反之亦然 – TLP

+0

意味着如果我只想替换第二个实例。 – aliocee

+0

是否必须恰好是两个实例,或者如果两个以上的实例发生替换? – ikegami

使用全局选项计数匹配,将匹配列表分配给空列表以获取计数(优于临时变量)。首先替换是基本的。其次使用计数器,每次比赛都会增加,并在适当的时间进行替换。

注意用字边界\b,防止错误匹配,如firefoxfoxy lady

代码:

use strict; 
use warnings; 
use v5.10; # only required for say, use print instead if your version is lower 

my $fox = 'fox'; 
my $wolf = 'wolf'; 
my $sen = "The quick brown fox jump over the lazy dog, fox is quick"; 

if ((()=$sen =~ /\b$fox\b/g) == 2) { # counting matches 
    my $first = $sen; 
    $first =~ s/\b$fox\b/$wolf/;  # replacing first 
    my $second = $sen; 
    my $i = 0; 
    $second =~ s/\b$fox\b/ ++$i == 2 ? $wolf : $fox/eg; # replacing second 
    say for $first, $second; 
} 

输出:

The quick brown wolf jump over the lazy dog, fox is quick 
The quick brown fox jump over the lazy dog, wolf is quick 

如果你希望有一个更可重用的代码,哟你可以制作一个子程序。

my $second = replace_nr($sen, $fox, $wolf, 2); 
... 
sub replace_nr { 
    my ($str, $find, $replace, $num) = @_; 
    my $i = 0; 
    $str =~ s/\b($find)\b/ ++$i == $num ? $replace : $find/eg; 
    return $str; 
} 

然后,您可以甚至使用子两个换人:

my $first = replace_nr($sen, $fox, $wolf, 1); 
my $second = replace_nr($sen, $fox, $wolf, 2); 
+0

我可以传递3作为参数吗? – aliocee

+0

@aliocee是的,你可以。但如果没有3场比赛,它将不会取代任何东西。在TLP: – TLP

+0

:我的匹配字符串中是否包含狐狸替换为狼? – aliocee

默认情况下,替换运算符的确如此:匹配并替换第一个匹配项。

下面的语句会得到您的第一输出线:

s/wolf/fox/ 
+0

如果我想匹配第二个呢? – aliocee

+0

@aliocee很好,你必须找到另一种模式。 –

要检查是否有(至少)两个并更换第一:

# The quick brown *wolf* jump over the lazy dog, fox is quick 
s/fox(?=.*fox)/wolf/s; 

要检查是否有(至少)两个和更换第二:

# The quick brown fox jump over the lazy dog, *wolf* is quick: 
s/fox.*\Kfox/wolf/s; 

s/(fox.*)fox/${1}wolf/s; # Slower, but works pre 5.10 
+0

谢谢,实例可以超过两个,请你能为我提供一个更好的匹配实例的方法吗? – aliocee

+0

很好的使用lookahead。 – kshenoy

+0

@aliocee,“实例”如果有三个实例是没有意义的。 – ikegami

您的新问题是,你想要的计数

my $count =() = $text =~ /fox/g; 

,并更换第N个实例

my $n = 3; 
my $nm1 = $n-1; 
$text =~ s/(?:fox.*){$nm1}\Kfox/s;