Reputation: 142
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
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
Reputation: 247210
sed
has an insert command:
sed '1n; /^pattern/i line to insert'
Upvotes: 4
Reputation: 36282
You already have some solutions, but, why yours doesn't work? Because sed 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 sed, 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
Reputation: 33387
With awk you could do something like this:
awk 'NR>1&&/pattern/{print "lineToInsert"}1' file
Upvotes: 3