sed, insert file before last line
The following inserting file method for sed
used to be working, even before last line, but not any more. Is it a bug in the current sed
?
Demo of inserting file method with sed:
mkdir /tmp/test
printf '%s\n' {1..3} > /tmp/test/f1
printf '%s\n' {one,two,three,four,five,six,seven,eight,nine,ten} > /tmp/test/f2
$ cat /tmp/test/f2 | sed -e "/nine/r /tmp/test/f1" -e //N
one
two
three
four
five
six
seven
eight
1
2
3
nine
ten
$ head -9 /tmp/test/f2 | sed -e "/nine/r /tmp/test/f1" -e //N
one
two
three
four
five
six
seven
eight
nine
1
2
3
$ cat /tmp/test/f2 | sed -e "/ten/r /tmp/test/f1" -e //N
one
two
three
four
five
six
seven
eight
nine
ten
1
2
3
$ sed --version
GNU sed version 4.2.1
...
I.e., the inserting file before the line method works everywhere except the last line. It used to be working before. Is it a bug in the current sed
?
Thanks
Solution 1:
Since you're on gnu sed
you could use
'e [COMMAND]'
This command allows one to pipe input from a shell command into
pattern space.
on the la$
t line:
sed '$e cat insert.txt' file
With ed
(replace ,p
with w
if you want to edit-in-place):
ed -s file<<IN
- r insert.txt
,p
q
IN
or
ed -s file <<< $'-1 r insert.txt\n,p\nq\n'
When ed
reads file
the current address is set to the la$
t line. -
(or -1
) sets the current address to one line before (i.e. $-1
) and r
reads in insert.txt
to after the current line. ,p
prints the content of the text buffer (as I said, replace with w
to save changes) and q
quits editor.
Solution 2:
According to your comment you "HAVE TO match against the last line", so I would consider using the $
(last line) and i
(insert command) in sed
. For example:
sed '$ i\INSERT BEFORE LAST LINE' number.txt
1
2
3
4
INSERT BEFORE LAST LINE
5
Just make sure that the file doesn't have an empty line as the last line and it should work. Note the the space between the dollar sign and the i
and the backslash (\
) after the i
. This will insert the text after the backslash to the last line without needed a /pattern/
for the last line.
NOTE: This command will only add one line of text before the final line, not a file. If you want to insert the contents of a file before the last line.
If you want to add an entire file (and you don't if it's in sed
) I would use this:
head -n-1 first_file.txt && cat inserted_file.txt && tail -n1 first_file.txt
This should display everything except the last line, then cat
the the inserted_file.txt
and then display the last line of the first_file.txt
.