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' > /tmp/test/f1 printf '%s\n' > /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

asked Jul 10, 2014 at 20:27 8,931 43 43 gold badges 115 115 silver badges 168 168 bronze badges

I've been trying hard to achieve it without success. I would switch to awk or perl , but just curiosity, which was the previous working version?

Commented Jul 11, 2014 at 8:52

I don't quite understand the mechanics of //N. But if you want to prepend text before the last line, why not just append it to the line before last? So, skip the //N then it will always append. Now you want text from file f1 before the last line $ echo -e 'one\ntwo\nthree\nfour' | sed -e '/three/r ./f1'

Commented Jul 11, 2014 at 13:22

"why not just append it to the line before last?" The problem is that you can't predict what the line before last would be, so I HAVE TO match against the last line, then insert before it. @Birei, I didn't keep the version, neither I kept the time I test it. But I dig the above from my note, which had been working before.

Commented Jul 11, 2014 at 14:08

@xpt I agree it'd be better to be more generic but you are predicting the last line because in your example you are stating it explicitly /ten/ so knowing beforehand that 'ten' was the last line.

Commented Jul 12, 2014 at 13:26

Exactly @barlop. Just like an html file, you don't know what its contents are, but a well formed html file would always have ' ' as the last time. Just an e.g.

Commented Jul 30, 2014 at 3:27

2 Answers 2

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 
ed -s file  

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.

answered Mar 29, 2015 at 15:55 don_crissti don_crissti 2,834 1 1 gold badge 21 21 silver badges 20 20 bronze badges

That works perfectly! (Tested with sed '$e cat /tmp/test/f1' /tmp/test/f2 using the files given in OP). Thanks!

Commented Mar 30, 2015 at 3:56

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 .