sed, insert file before last line

7

1

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

xpt

Posted 2014-07-10T20:27:02.260

Reputation: 5 548

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? – Birei – 2014-07-11T08:52:07.277

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' – barlop – 2014-07-11T13:22:07.323

"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. – xpt – 2014-07-11T14:08:07.800

@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. – barlop – 2014-07-12T13:26:20.737

Exactly @barlop. Just like an html file, you don't know what its contents are, but a well formed html file would always have '</body>' as the last time. Just an e.g. – xpt – 2014-07-30T03:27:38.340

Answers

5

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.

don_crissti

Posted 2014-07-10T20:27:02.260

Reputation: 2 374

That works perfectly! (Tested with sed '$e cat /tmp/test/f1' /tmp/test/f2 using the files given in OP). Thanks! – xpt – 2015-03-30T03:56:06.020

6

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.

skamazin

Posted 2014-07-10T20:27:02.260

Reputation: 169

that puts a line before the last line but he said insert a file before the last line – barlop – 2014-07-29T19:22:49.883

1This method puts a line before the last line, but it doesn't insert a file that it true. I'll make note of that in my answer. Thanks – skamazin – 2014-07-29T19:41:33.373

1your 'answer' might be worthy as a comment but i'm sure the op is aware of it and it doesn't answer the question – barlop – 2014-07-29T19:44:19.260