Reputation: 2350
I've noticed something weird:
Y=""
echo ${Y:-"\n"}
echo "${Y:-"\n"}"
prints
\n
n
Why is the second line n
, not \n
? Is this a bug?
It looks as if Bash parsed this as a concatenation of two quoted strings with an unquoted string in between ("${Y:-"
and \n
and "}"
) but this doesn't seem to be the case since the commands
echo $(echo "\n")
echo "$(echo "\n")"
echo "${Y:-"'\n'"}"
output
\n
\n
'n'
I'm using GNU bash, version 4.3.11.
Upvotes: 3
Views: 223
Reputation: 440546
To complement chepner's helpful answer:
Here's an overview of how the major POSIX-like shells handle the following command:
Y=""
printf '%s\n' ${Y:-"\n"} ${Y:-'\n'} "${Y:-"\n"}" "${Y:-'\n'}"
Note that I've added variations with single quotes.
dash [v0.5.8]
\n
\n
\n
'\n'
zsh [v5.0.8]
\n
\n
\n
'\n'
bash [v4.3.42]
\n
\n
n
'\n'
ksh [93u+]
\n
\n
n
'\n'
Curiously, in all shells, '\n'
inside "..."
preserves the single quotes, while removing them in the unquoted case.
With respect to "\n"
, both bash
and ksh
exhibit the oddity uncovered by the OP, while dash
and zsh
do not.
Upvotes: 2
Reputation: 84652
Maybe I'm looking at this wrong, but I don't seen any inconsistency in the assignment with the default value Y
, quoted or unquoted. The echo
expression in each case boils down to:
$ echo "\n"
\n
$ echo ""\n""
n
In the first case you have the quoted string "\n"
, in the second, you have a bare \n
(which is simply n
)
Upvotes: 0
Reputation: 532418
I suspect there is a bug in the handling of the word following :-
(in fact, I seem to recall reading something about this, but I can't recall where).
If the value is not quoted, I get results I would expect...
$ echo ${Y:-\n}
n
$ echo "${Y:-\n}"
\n
This is also the result you get in dash
(ignoring the fact that dash
actually produces a literal newline since POSIX mandates that echo
should process escaped characters, something bash
only does if you use the non-standard -e
option.)
In this example, quoting the default value preserves the backslash. As the result of the parameter expansion produces the backslash, quote removal does not remove it.
$ echo ${Y:-"\n"} # Equivalent to echo "\n", so the output makes sense
\n
There doesn't seem to be any reason for bash
to behave different in this final example just because the entire parameter expansion is being quoted. It is almost as if quote removal is being applied twice, once to remove the outer double quotes and again to incorrectly remove the backslash.
# Quote removal discards the backslash: OK
$ echo \n
n
# Quote removal discards the double quotes: OK
$ echo "n"
n
# Quote removal discards the first backslash after `\\` is recognized
# as a quoted backslash: OK
$ echo \\n
\n
# Quote removal discards the double quotes, but leaves
# backslash: OK
$ echo "\n"
\n
# Is quote removal discarding both the double quotes *and* the backslash? Not OK
$ echo "${Y:-"\n"}"
n
Related, zsh
(with the bsd_echo
) option set outputs \n
, not n
.
% Y=""
% echo "${Y:-"\n"}"
\n
Upvotes: 3