Devos
Devos

Reputation: 142

Inserting line between two lines having second line starting with certain pattern

I want to insert a line between two lines, only if the second line matches a certain pattern

for example the input file is as follows:

pattern (match 1, line 1)
line 2
line 3
line 4
line 5 (before pattern)
pattern (match 2, line 5)
line 7
line 8
line 9
line 10 (before pattern)
pattern (match 3, line 11)
line 12

I want to insert lineToInsert between line 5 and pattern and between line 10 and pattern

I have tried this command:

sed 'N;s/\n\(pattern\)/\n\ 
lineToInsert\n\1/'

I expect this to work, but it only works if the matched pattern exists on an even line only !!

So, How could I achieve this using sed or any other tool / command? and Why the previous command does not work ?

Upvotes: 4

Views: 4171

Answers (4)

potong
potong

Reputation: 58578

This might work for you (GNU sed):

sed -e '$!N;/\npattern/a\insert line' -e 'P;D' file

This reads 2 lines into the pattern space and then looks for the pattern at the beginning of the second line. If it finds the pattern it appends the new line to the first line. At all times it prints the first line and then deletes it thus invoking the $!N without reading in a new line automatically as sed normally does. The D command overides the automatic reading in of a new line when a newline (\n) exists already in the pattern space.

Because you were not using the P;D combination you were always reading lines in two at a time.

Of course this can easier be handled using:

sed '1n;/^pattern/i\insert new line' file # as in Glen Jackman's answer

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 247210

sed has an insert command:

sed '1n; /^pattern/i line to insert'

Upvotes: 4

Birei
Birei

Reputation: 36282

You already have some solutions, but, why yours doesn't work? Because reads each line and N reads the next one and appends it to the current one. So you save into the buffer each pair of two lines and apply the substitution command to both of them joined with a newline character.

Your buffer after the execution of the N command will be:

pattern\nline 2

Later:

line 3\nline 4

Later:

line 5 \npattern

and so on.

In your substitution command you have a newline character just before the pattern, so it will only succeed when the pattern is in the second line, or said another way, an even one.

With , you can avoid N and process the file line by line and don't worry about newlines, like:

sed '1! s/\(pattern\)/lineToInsert\n\1/' infile

It yields:

pattern 
line 2
line 3
line 4
line 5 
lineToInsert
pattern 
line 7
line 8
line 9
line 10 
lineToInsert
pattern 
line 12

Upvotes: 3

user000001
user000001

Reputation: 33387

With awk you could do something like this:

awk 'NR>1&&/pattern/{print "lineToInsert"}1' file

Upvotes: 3

Related Questions