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

时间:2011-12-13 07:54:30

标签: regex 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 

感谢。

4 个答案:

答案 0 :(得分:3)

使用全局选项/g计算匹配项,将匹配列表分配给空列表以获取计数(优于临时变量)。第一次更换是基本的。第二个使用一个计数器,为每个匹配增加,并在适当的时间替换。

请注意使用单词边框\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;
}

然后你甚至可以使用sub进行两次替换:

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

答案 1 :(得分:2)

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

# 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

答案 2 :(得分:1)

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

以下语句将为您提供第一个输出行:

s/wolf/fox/

答案 3 :(得分:0)

您的新问题是您想要点数

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

并替换第N个实例

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