-2

How to write a sed (or awk, or both) which will take the following:

echo '1 aa 2 2 3 bb 5 bb 2 5' | sed/awk ...

And only replace the n-th occurrence of a string? For example the 3rd occurrence of 2 or the second occurrence of bb?

So the expected output would be (when replacing 2nd occurrence of bb with replaced for example):

1 aa 2 2 3 bb 5 replaced 2 5

The input string, the replacement string, and n can be any arbitrary input.

4
  • 1
    do you want to change abb bb bb into abb CHG bb or abb bb CHG (?) when it's a change of the second match of the string bb. I. e, do you want strings as if they are a word boundaries or partial match like in abb? May 14 at 7:21
  • And what about bbbb? You can argue, that the first and second b form the first bb and the second and third form the second bb (-> bBBb). The sed interpretation is non-overlapping matches, so the third and forth b form the second match (-> bbBB)
    – Philippos
    yesterday
  • 1
    @αғsнιη not sure why you sent this ("see also..."). My question was only asked two days ago. I am quite busy both professionally and personally and my Sundays are for God. Furthermore, I feel that my description was clear enough. The answer to your questions are already in my post: The input string, the replacement string, and n can be any (sensical) arbitrary input.. As such, it is partial/exact match. yesterday
  • 1
    @Philippos thank you for the question. If the string was bbbb and b was searched for then we would have 4 occurrences. If the bb was searched for then we would have 2 max occurrences (one could say that as soon as the first bb was found, it would be replaced). Also, search/replace should not be recursive (for example where the replace string would be bbb etc.) yesterday

4 Answers 4

5

Using sed to change the second occurance of bb

$ sed 's/bb/new-bb/2' file
1 aa 2 2 3 bb 5 new-bb 2 5

or to change the third occurance of 2

$ sed 's/2/12/3' file
1 aa 2 2 3 bb 5 bb 12 5
1
  • 1
    I did not know there was an option like this in sed. Simple and beautiful, thank you. yesterday
4

To change the nth occurrence within a line, sed has syntax for that with s/pattern/replacement/3 as already shown by @HatLess.

To change the nth occurrence in the whole input, you could use perl with:

perl -pse 'if($n>0) {s{pattern}{--$n ? $& : "replacement"}ge}' -- -n=3
2

With awk you could do:

awk -v str='bb' -v pos=2 -v rplc='newBB' '
 {
   strPos=0
   for(i=1; i<=NF; i++)
       if($i==str && (++strPos==pos) ) { $i=rplc; break }
 }1' infile

Output:

1 aa 2 2 3 bb 5 newBB 2 5

Note: Above it assumes that there is only a sinlge character as the field separator (defualt: Space or Tab) since otherwise consecutive field separator will squeeze into one or you can force awk to match on each single field separator separately (so the FS must be forced as regex mode):

awk -F'[\t]' -v OFS='\t' -v str='bb' -v pos=2 -v rplc='newBB' '
 {
   strPos=0
   for(i=1; i<=NF; i++)
      if($i==str && (++strPos==pos) ) { $i=rplc; break }
 }1' infile

Note: change \t to Space character if the field seperator is Space chartacter.


To change the nth occurrence in the whole input (yet I assumed field seperator is the Tab character):

awk -F'[\t]' -v OFS='\t' -v str='bb' -v pos=2 -v rplc='newBB' '
 strPos!=2{
            for(i=1; i<=NF; i++)
                if($i==str && (++strPos==pos) ) { $i=rplc; break }
 }1' infile
4
  • Thank you! Is there an extra ' at the end of the first line? May 14 at 7:00
  • 1
    @RoelVandePaar you are welcome! and no, that is not extra. May 14 at 7:14
  • @RoelVandePaar The awk program is formatted multi-line for clarity, and the matching quote is on the last line. May 14 at 8:11
  • Thank you for the input. I like the simplicity of the sed but this is a valuable extra on awk to learn from. yesterday
1

We can do both with sed in a single command:

echo "1 aa 2 2 3 bb 5 bb 2 5"|sed -e "s/2/kop/3" -e "s/bb/pp/2"

This command will replace 3rd occurrence of 2 with kop and 2nd occurrence of bb with pp.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.