1

I want to replace all excluding first result

I have txt file:

AAA
BBB
CCC
AAA
BBB
CCC
AAA
BBB
CCC

I want to get this:

AAA
BBB <-- stay same
CCC
AAA
XXX <-- 2nd find replaced
CCC
AAA
XXX <-- 3rd and nth find replaced
CCC

I looking something similar to this, but for whole lines, not for words in lines

sed -i 's/AAA/XXX/2' ./test01
Sundeep
  • 21,380
  • 2
  • 23
  • 85
Tomasz Stanik
  • 63
  • 1
  • 5

5 Answers5

4

Use branching:

sed -e'/BBB/ {ba};b; :a {n;s/BBB/XXX/;ba}' 

I.e. on the first BBB, we branch to :a, otherwise b without parameter starts processing of the next line.

Under :a, we read in a new line, replace all BBB by XXX and branch to a again.

choroba
  • 216,930
  • 22
  • 195
  • 267
0

Following awk may also help you on same.

awk '{++a[$0];$0=$0=="AAA"&&(a[$0]==2||a[$0]==3)?$0 ORS "XXX":$0} 1' Input_file
RavinderSingh13
  • 117,272
  • 11
  • 49
  • 86
0
$ # replace all occurrences greater than s
$ # use gsub instead of sub to replace all occurrences in line
$ # whole line: awk -v s=1 '$0=="AAA" && ++c>s{$0="XXX"} 1' ip.txt
$ awk -v s=1 '/AAA/ && ++c>s{sub(/AAA/, "XXX")} 1' ip.txt 
AAA
BBB
CCC
XXX
BBB
CCC
XXX
BBB
CCC

$ # replace exactly when occurrence == s
$ awk -v s=2 '/AAA/ && ++c==s{sub(/AAA/, "XXX")} 1' ip.txt 
AAA
BBB
CCC
XXX
BBB
CCC
AAA
BBB
CCC

Further reading: Printing with sed or awk a line following a matching pattern

Sundeep
  • 21,380
  • 2
  • 23
  • 85
0
awk  '/BBB/{c++;if(c >=2)sub(/BBB/,"XXX")}1' file

AAA
BBB
CCC
AAA
XXX
CCC
AAA
XXX
CCC
Claes Wikner
  • 1,397
  • 1
  • 8
  • 7
0

As soon as your file does not contain null chars (\0) you can fool sed to consider the whole file as a big string by intstructing sed to separate records using null char \0 instead of the default \n with sed option -z:

$ sed -z 's/BBB/XXX/2g' file66
AAA
BBB
CCC
AAA
XXX
CCC
AAA
XXX
CCC

/2g at the end means from second match and then globally.

You can combine -i with -z without problem.

George Vasiliou
  • 5,755
  • 2
  • 17
  • 26