In a Linux shell, why does backslash-newline not introduce whitespace?
When using the Linux shell, I come across the following situation:
$ A=B\
> C
$ echo $A
BC
In my mind, when the newline encountering escape character, it can not be a CR character but it still be a newline. The echo $A
should be interpret as echo B newline C
and the newline should be an IFS for echo
. So the output should be B C
instead of BC
.
Why do I get the output I do?
Solution 1:
Quoting man bash
, section QUOTING:
A non-quoted backslash (
\
) is the escape character. It preserves the literal value of the next character that follows, with the exception of<newline>
. If a\<newline>
pair appears, and the backslash is not itself quoted, the\<newline>
is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).
This allows you to break very long commands / command sequences (piping and transforming output etc.) in scripts into multiple lines for readability.
To get it to treat the newline as you expect, just wrap the value (and any later use of the variable) in quotes.
$ A="B
> C"
$ echo "$A"
B
C
From the same section:
Enclosing characters in single quotes preserves the literal value of each character within the quotes. ...
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `,
\
, and, when history expansion is enabled, !. The characters $ and ` retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ",\
, or .
Solution 2:
Answering the "why" as "why is this useful":
The Backslash-newline is used for line continuation to split ovely long lines:
A backslash at the end of a line in a shell script makes the shell ignore the newline for the purposes of executing the script. This is normally used to split long lines in a script file into multiple text lines, which will be handeled as a single script line by the shell.
For example, the command
git log --tags --branches HEAD FETCH_HEAD ORIG_HEAD --graph --decorate --pretty=oneline --simplify-by-decoration
can be written as
git log --tags --branches HEAD FETCH_HEAD ORIG_HEAD \
--graph --decorate --pretty=oneline --simplify-by-decoration
Solution 3:
Caveat: Backslash continues a line only if it is the very last character in the line.
This is somewhat off-topic; I add it here as an easily-overlooked show-stopper. If you inadvertently end a line in your shell script with \
(backslash followed by space or tab) rather than \
you may find your script stops running or otherwise behaves unexpectedly even though backslash appears to be the last character.
If you are editing with vi it is easy to spot this problem with the command :set list
, which will place a $ at the end of every line, allowing you to spot trailing spaces or tabs. :set nolist
turns this feature of vi off.