Reputation: 730
I want to replace only the first instance if two matches returned.
example:
$sen = "The quick brown fox jump over the lazy dog, fox is quick";
how can i match only the first fox and replace it with wolf and vice versa.
Output:
The quick brown wolf jump over the lazy dog, fox is quick
or:
The quick brown fox jump over the lazy dog, wolf is quick
Thanks.
Upvotes: 3
Views: 836
Reputation: 385655
To check if there are (at least) two and replace the first:
# The quick brown *wolf* jump over the lazy dog, fox is quick
s/fox(?=.*fox)/wolf/s;
To check if there are (at least) two and replace the second:
# 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
Upvotes: 2
Reputation: 385655
Your new question is that you want the count
my $count = () = $text =~ /fox/g;
and to replace the Nth instance
my $n = 3;
my $nm1 = $n-1;
$text =~ s/(?:fox.*){$nm1}\Kfox/s;
Upvotes: 0
Reputation: 67900
Counting matches by using global option /g
, assign list of matches to an empty list to get a count (better than a temp variable). First replace is basic. Second uses a counter that increments for each match, and replaces at the proper time.
Note use of word border \b
to prevent false matches, such as firefox
, foxy lady
, etc.
Code:
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;
}
Output:
The quick brown wolf jump over the lazy dog, fox is quick
The quick brown fox jump over the lazy dog, wolf is quick
If you wish a more reusable code, you can make a subroutine out of it.
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;
}
You could then even use the sub for both substitutions:
my $first = replace_nr($sen, $fox, $wolf, 1);
my $second = replace_nr($sen, $fox, $wolf, 2);
Upvotes: 3
Reputation: 42094
By default, the substitution operator does exactly that: match and replace the first occurence.
The following statement will get you your first output line:
s/wolf/fox/
Upvotes: 1