2

In sed you can replace the Nth match using /N (solved so long ago):

$ sed 's/you/ME/1' <<< "hello you are you"  # 1 is superfluous here, though
hello ME are you
$ sed 's/you/ME/2' <<< "hello you are you"
hello you are ME

I am trying to accomplish the same in awk and the only dirty way I found is looping through the elements and keeping a counter.

Even the simpler case, where the match is a full field, gets a bit dirty:

$ awk '{for (i=1;i<=NF;i++) if ($i=="you" && ++c==2) $i="ME"}1' <<< "hello you are you"
hello you are ME

Thus, I wonder if any of the gensub(), gsub() or sub() functions allow you to provide such parameter to do it in a more straight-forward way. Going through the String functions in the GNU awk manual did not show help me to find it.

Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598

1 Answers1

3

Try with gensub(). I think it's only included in version, but it accepts a regular expression to match, replacement text and the position:

awk '$0 = gensub(/you/, "ME", 1)' <<< "hello you are you"

that yields:

hello ME are you

and

awk '$0 = gensub(/you/, "ME", 2)' <<< "hello you are you"

that yields:

hello you are ME
Birei
  • 35,723
  • 2
  • 77
  • 82
  • 1
    Ooooh I tried this one but I did not remember `gensub()` doesn't replace `$0` but outputs it. That is, `awk 'gensub(/you/, "ME", 2)'` did not work to me because it was printing the original value. Nice one, many thanks! – fedorqui Dec 08 '15 at 17:34