How to use sed or ex to replace a block (multi-line code) with new block of text (code)

exsed

I have to replace a large block of a text (shell script code) in a file with another block of text.

I am impressed with the How can I use sed to replace a multi-line string? answered by
antak and Multi-line replace answered by Bruce Ediger

But I have some trouble in using them.

  1. antak already mentioned in his answer that streaming entire file (1h;2,$H;$!d;g;) to the buffer is not advisable for large files, because it overload memory.

  2. I know sed can be used with the block feature to preserve the text outside the block unchanged. I want to use this feature. But if I use,

    sed -i '/marker1/,/marker2/s/.*/new text (code)/' filename
    

it will insert new text (code) repeatedly for each stream. Hence I have to make the visual block as one stream, using something similar to what suggested by antak earlier, but for the block (not for entire file).

  1. As mentioned by Bruce Ediger append feature of ex which begin with a end with .(dot) can be tried, but my new text (code) contain lines begin with dot, which may be considered as the dot of append syntax. How can I use it in this situation?

  2. ex's dd 'number of lines' may delete multiple lines, but if I have a block between /marker1/ and /marker2/ with the number of lines not fixed (varying) is to be replaced with new text (code), how to do it ?

Best Answer

I suggest using the change command (which is essentially a delete coupled with an append, though the append is only applied for the last line in the range which is exactly what you want here):

sed -i '/marker1/,/marker2/c\
New text 1\
New text 2' filename

Here using GNU sed's syntax for in-place editing (-i). That c command is otherwise standard and portable. GNU sed supports:

sed '/marker1/,/marker2/cNew text 1\
New text 2' filename

as a non-standard extension.

Newline and backslash characters must be escaped (with backslash) in the replacement text.

Related Question