I'd like to insert multiple lines in a file by using sed.
The file.txt
below contains one line "target line
". My initial version is:
sed '/target line/ i\
inserted line1;\
inserted line2;\
inserted line3;' file.txt
This version works as expected that the newline is escaped by "\" at the end of the line. Refer to
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.
After some trial and error, I found this version works with double quotes:
sed "/target line/ i\
\ inserted line1;\n\
inserted line2;\n\
inserted line3;" file.txt
This behavior confuses me. What is the mechanism under the hood here?
CodePudding user response:
With single-quotes:
The backslash followed by the newline are transmitted as-is to sed. Although, sed just ignores the backslash. 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
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