i was just going thorugh this and i was unable to understand.

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.

where cat file is :


why there is 1!H because to me 1h overwrites the pattern space and 1!H is of no use

But the sed one liner seems to work fine.


See @manatwork's answer for the actual reason for 1h;1!H, but I wanted to add a portability note.

The standard and portable syntax should be:

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\

Otherwise it won't work in most sed implementations, for instance the traditional Unix ones.

That is \n is understood on the left hand side of the s command, but you have to use a backslash character followed by an actual newline character on the right hand side. You also need the ; between the s command and }, and no space before the p.

You could also store the content of the file in the pattern space instead of the hold space:

sed -n '

But with both pattern and hold space, with most sed implementations that will only work with small files as most non-GNU implementations have a limited size for those (and POSIX only requires them to be able to hold 8kiB of data).

Portably, you'd be better off using perl:

perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'

Because the size is not limited in perl or GNU sed however beware that it may have an incidence on the performance of the system as it may end up using all the system memory if you don't have administratively set limits on per-process memory usage.

  • If you're going for historical implementations, you can't use semicolons as separators either. They are supported in recent POSIX versions and in OpenBSD and in BusyBox though. The lack of a ; before } does confuse OpenBSD. – Gilles May 3 '13 at 23:04
  • @Gilles, not sure what implementation you had in mind, but that syntax works in Unix V7 (1979), just tested on a PDP11 emulator. By historical implementations, I meant the ones found for instance in the commercial Unices like AIX/Solaris/HPUX... descendants of Unix, or the one found in the Heirloom toolchest (port of OpenSolaris toolchest to Linux) – Stéphane Chazelas May 4 '13 at 7:29

why there is 1!H because to me 1h overwrites the pattern space and 1!H is of no use

No overwriting occurs as they are not executed on the same input line:

1h   # when input line number is 1, copy pattern space to hold space
1!H  # when input line number is not 1, append pattern space to hold space

That is necessary because according to info sed:

     Append a newline to the contents of the hold space, and then
     append the contents of the pattern space to that of the hold space.

So if you use just H to append all lines, there will be an extra newline before the first line:

bash-4.2$ seq 3 | sed -n 'H; ${g; p;}'

bash-4.2$ seq 3 | sed -n '1h; 1!H; ${g; p;}'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.