Reputation: 31
I have the following problem.
I have a file with sequence and I want to find a specific pattern and replace it with another pattern, but only for a specific number of times.
eg:
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
I want to find "DEFGHI" and replace it with "ABCDEF" for only 3 times.
sed -i 's/DEFGHI/ABCDEF/g' /home/user/test.txt
I don't want to replace globally; instead I want to replace only 3 times.
Upvotes: 1
Views: 2715
Reputation: 10149
This can be done using bash and GNU sed like this:
sed -z -i "$(echo s/DEFGHI/ABCDEF/{3..1}\;)" yourfile
{3..1}
results in the the s
part repeated three time with flag 3 to 1. Each s
command replaces only the third, second and first occurence. The inverted order is necessary, so that the counting and replacing do not mix up.-z
takes all the input lines at once, thus the counting is not per line but per file.For your reference, here is what the command substitution around the echo produces:
echo s/DEFGHI/ABCDEF/{3..1}\;
> s/DEFGHI/ABCDEF/3; s/DEFGHI/ABCDEF/2; s/DEFGHI/ABCDEF/1;
Upvotes: 2
Reputation: 66883
This replaces the given pattern three times, whichever way they're distributed over lines
perl -0777 -pe'$i += s/DEF/xxx/ while $i < 3' < data.txt > out.txt
It assumes that the pattern is not broken over lines. It makes passes over the string, searching from the beginning each time. This comes with a caveat explained below and is ineffcient but it is simple.
If the replacement itself recreates the pattern when combined with the surrounding text, this will also be replaced in the next pass. Such a replacement would have to contain parts of the pattern itself and in a specific way. Still, if this is a concern let me know.
Handling of possible overlapping patterns is not specified in the problem. If there are any this solution will replace the first so in the next pass the overlapping one will have been gone.
Upvotes: 2
Reputation: 15461
You can replace the first occurrence found three times:
sed -i '0,/DEFGHI/s//ABCDEF/;0,/DEFGHI/s//ABCDEF/;0,/DEFGHI/s//ABCDEF/' file
output:
ABCABCDEFJKLMN
ABCABCDEFJKLMN
ABCABCDEFJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
Upvotes: 0