Home > front end >  How to insert newline in the argument text of "sed" utility under both single and double q
How to insert newline in the argument text of "sed" utility under both single and double q

Time:07-02

I'd like to insert multiple lines above a target line in a file by using sed.

The file.txt below contains one line "target line". My initial version is using the single quote:

sed '/target line/ i\
     inserted line1;\
     inserted line2;\
     inserted line3;' file.txt

The result is:

    inserted line1;
    inserted line2;
    inserted line3;
target line

This version works as expected that the newline at the end of each line is escaped by \ to a literal newline instead of a command terminator. Refer to here.

Then I'd like to use shell variable in the replacement string, so I tried to use double quotes to enable the variable expansion:

sed "/target line/ i\
     inserted line1;\
     inserted line2;\
     inserted line3;" file.txt

But this time the newline and the first four spaces disappeared:

inserted line1;    inserted line2;    inserted line3;
target line

How do I correctly insert a newline in double quotes here?

CodePudding user response:

With single-quotes:

The backslash followed by the newline are transmitted as-is to sed. Then sed actually uses the backslash to escape the raw newline character into the string rather than terminating the command. See:

$ printf %s 'hello\
world' | hexdump -C

Which clearly shows the backslash 5c followed by the newline 0a contained in the string.

00000000  68 65 6c 6c 6f 5c 0a 77  6f 72 6c 64              |hello\.world|
0000000c

With double-quotes:

The backslash has special meaning in double-quotes. It causes the following newline character to be interpreted as a string continuation character. The consequence is that neither the backslash or the newline are contained in the string and so not seen by sed.

$ printf %s "hello\
world" | hexdump -C

The string is continued without backslash and without newline:

00000000  68 65 6c 6c 6f 77 6f 72  6c 64                    |helloworld|
0000000a

EDIT:

  • Precised that sed actually uses the backslash to escape the following newline character as @dan pointed out.

CodePudding user response:

In double quotes, backslash escapes these characters (only):

$`"\

and newline character. So eg echo "\$" prints $.

To preserve the backslash in double quotes, escape it with another backslash:

 sed "/target line/ i\\
     inserted line1;\\
     inserted line2;\\
     inserted line3;" file.txt
  • Related