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
abb bb bb
intoabb CHG bb
orabb bb CHG
(?) when it's a change of the second match of the stringbb
. I. e, do you want strings as if they are a word boundaries or partial match like inabb
? – αғsнιη May 14 '22 at 07:21bbbb
? You can argue, that the first and secondb
form the firstbb
and the second and third form the secondbb
(->bBBb
). Thesed
interpretation is non-overlapping matches, so the third and forthb
form the second match (->bbBB
) – Philippos May 16 '22 at 07:22The input string, the replacement string, and n can be any (sensical) arbitrary input.
. As such, it is partial/exact match. – Roel Van de Paar May 16 '22 at 11:15bbbb
andb
was searched for then we would have 4 occurrences. If thebb
was searched for then we would have 2 max occurrences (one could say that as soon as the firstbb
was found, it would be replaced). Also, search/replace should not be recursive (for example where the replace string would bebbb
etc.) – Roel Van de Paar May 16 '22 at 11:18