Diving
Diving

Reputation: 914

Shell script: Insert multiple lines into a file ONLY after a specified pattern appears for the FIRST time. (The pattern appears multiple times)

I want to insert multiple lines into a file using shell script. Let us consider my original file: original.txt:

aaa
bbb
ccc
aaa
bbb
ccc
aaa
bbb
ccc
.
.
.

and my insert file: toinsert.txt

111
222
333

Now I have to insert the three lines from the 'toinsert.txt' file ONLY after the line 'ccc' appears for the FIRST time in the 'original.txt' file. Note: the 'ccc' pattern appears more than one time in my 'original.txt' file. After inserting ONLY after the pattern appears for the FIRST time, my file should change like this:

aaa
bbb
ccc
111
222
333
aaa
bbb
ccc
aaa
bbb
ccc
.
.
.

I should do the above insertion using a shell script. Can someone help me?

Note2: I found a similar case, with a partial solution:

sed -i -e '/ccc/r toinsert.txt' original.txt

which actually does the insertion multiple times (for every time the ccc pattern shows up).

Upvotes: 1

Views: 607

Answers (2)

potong
potong

Reputation: 58371

This might work for you (GNU sed):

sed '0,/ccc/!b;/ccc/r insertFile' file

Use a range:

If the current line is in the range following the first occurrence of ccc, break from further processing and implicitly print as usual.

Otherwise if the current line does contain ccc,insert lines from insertFile.

N.B. This uses the address 0 which allows the regexp to occur on line 1 and is specific to GNU sed.

or:

sed -e '/ccc/!b;r insertFile' -e ':a;n;ba' file

Use a loop:

If a line does not contain ccc, no further processing and print as usual.

Otherwise, insert lines from insertFile and then using a loop, fetch/print the remaining lines until the end of the file.

N.B. The r command insists on being delimited from other sed commands by a newline. The -e option simulates this effect and thus the sed commands are split across two -e options.

or:

sed 'x;/./{x;b};x;/ccc/!b;h;r insertFile' file

Use a flag:

If the hold space is not empty (the flag has already been set), no further processing and print as usual.

Otherwise, if the line does not contain ccc, no further processing and print as usual.

Otherwise, copy the current line to the hold space (set the flag) and insert lines from insertFile.

N.B. In all cases the r command inserts lines from insertFile after the current line is printed.

Upvotes: 2

Shawn
Shawn

Reputation: 52334

Use ed, not sed, to edit files:

printf "%s\n" "/ccc/r toinsert.txt" w | ed -s original.txt

It inserts the contents of the other file after the first line containing ccc, but unlike your sed version, only after the first.

Upvotes: 3

Related Questions