Reputation: 24423
I have been using this code, to replace the first occurrence of a pattern in a file:
sed "0,\#pattern#s##replacement#" input.txt > output.txt
To replace the first 5 occurrences of a pattern in a file, I used this:
sed "0,\#pattern#s##replacement#" input.txt > output1.txt
sed "0,\#pattern#s##replacement#" output1.txt > output2.txt
sed "0,\#pattern#s##replacement#" output2.txt > output3.txt
sed "0,\#pattern#s##replacement#" output3.txt > output4.txt
sed "0,\#pattern#s##replacement#" output4.txt > output5.txt
mv output5.txt output.txt
How can I more simply replace the first n
appearances of a match with sed
?
Upvotes: 0
Views: 155
Reputation: 15501
sed
has no natural counting ability. You could do something weird like this.
sed -r '
/pattern/ {
s//replacement/
x
s/.*/&x/
t clear
: clear
s/x{3}/&/
x
T
q
}
' file
In the last substitute command, set the number of x
's to the number of substitutions you want. In practice this command would need to be used with -i
to modify the file in place since it quits and stops processing the file after it performs the requested number of substitutions.
The above with comments:
sed -r '
/pattern/ {
s//replacement/
x # exchange spaces
s/.*/&x/ # increment number of x s
t clear # reset the successul substitition flag
: clear
s/x{3}/&/ # test for the required number of x s to quit
x # exchange spaces
T # if substitution was not successful, next cycle
q # quit
}
' file
Here's another idea, but it can only go up to 10 replacements.
sed -r '
1{x;s/^/0/;x}
/pattern/ {
s//replacement/
x
y/0123456789/1234567890/
tx :x # reset substitution flag
s/3/&/
x; T; q
}'
If you're using a sed
that doesn't have the T
command, it can be replaced with it's opposite, the t
command. Change:
T
q
to
t quit
b
: quit
q
Upvotes: 2
Reputation: 241881
This is not really a natural job for sed
(personally I'd used awk
) but the following should work:
sed '1{x;s/.*/00000/;x};/PATTERN/{x;s/0//;x;t1;b;:1;s/PATTERN/REPLACEMENT/}'
The length of the string of 0
s in the first s
command is the number of replacements; I used 0
with the intention of generating the sed
command as follows:
sed "1{x;s/.*/$(printf %*d $COUNT 0)/;x};
/$PATTERN/{x;s/0//;x;t1;b;:1;s/$PATTERN/$REPLACEMENT/}"
With Gnu sed
, you can replace t1;b;:1;
with T;
Here's the awk version:
awk 'N&&sub(PAT,REPL){N--};1' N=5 PAT="pattern" REPL="replacement"
Upvotes: 4
Reputation: 98088
You can also consider perl:
perl -lpe 's#pattern#s##replacement# and $n++ if $n < 5' input
Upvotes: 1