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
  • 23,246
  • 2
  • 28
  • 103
Tomasz Stanik
  • 73
  • 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
  • 231,213
  • 25
  • 204
  • 289
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
  • 130,504
  • 14
  • 57
  • 93
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
  • 23,246
  • 2
  • 28
  • 103
0
awk  '/BBB/{c++;if(c >=2)sub(/BBB/,"XXX")}1' file

AAA
BBB
CCC
AAA
XXX
CCC
AAA
XXX
CCC
Claes Wikner
  • 1,457
  • 1
  • 9
  • 8
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
  • 6,130
  • 2
  • 20
  • 27