Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux bash: How do I replace a string on a line based on a pattern on another/different line?

Tags:

linux

bash

sed

I have a file that contains the following data:

GS*PO*112233*445566*20211006*155007*2010408*X*004010~

ST*850*0001~
BEG*00*DS*A-112233**20211005~
REF*K6*Drop Ship Order~
REF*ZZ*SO168219~
REF*DC*ABC~

ST*850*0002~
BEG*00*DS*A-44556**20211005~
REF*K6*Drop Ship Order~
REF*ZZ*PO54361~

ST*850*0003~
BEG*00*DS*A-12345**20211005~
REF*K6*Drop Ship Order~
REF*DC*XYZ~
REF*ZZ*SO897654~

For clarity, I have inserted blank line above each ST*850 line. Here is what I want to do:

  1. Search for the pattern REF*ZZ*SO
  2. If found, then replace the preceding ST*850 line with ST*850C

So the resultant file would look like this:

GS*PO*112233*445566*20211006*155007*2010408*X*004010~

ST*850C*0001~
BEG*00*DS*A-112233**20211005~
REF*K6*Drop Ship Order~
REF*ZZ*SO168219~
REF*DC*ABC~

ST*850*0002~
BEG*00*DS*A-44556**20211005~
REF*K6*Drop Ship Order~
REF*ZZ*PO54361~

ST*850C*0003~
BEG*00*DS*A-12345**20211005~
REF*K6*Drop Ship Order~
REF*DC*XYZ~
REF*ZZ*SO897654~

Here is what I have tried:

sed -i -n '/^REF\*ZZ\*SO/!{x;s/ST\*850\*/ST\*850C\*/;x};x;1!p;${x;p}' file

This replaces all the three ST*850 lines with ST*850C and not just the 1st and the 3rd. What am I doing wrong?

like image 840
user3152289 Avatar asked Dec 08 '22 09:12

user3152289


1 Answers

This might work for you (GNU sed):

sed '/ST\*850/{:a;/REF\*ZZ\*SO/!{N;ba};s/.*ST\*850/&C/}' file

Begin gathering up lines if a line contains ST*850.

On matching a line that contains REF*ZZ*SO use greed to append C to the latest ST*850 string.

N.B. The regexp .* ensures that the match will backtrack from the end of the collection rather than the start of the collection.

like image 153
potong Avatar answered Jan 04 '23 23:01

potong