When using BASH Parameter Expansion, string that variable expands into can be quoted/escaped, which works fine, except when the single quotes are used and the whole variable is escaped in double quotes:
$ echo "${var:-\\a}"
\a # ok
$ echo "${var:-"\\a"}"
\a # ok
$ echo "${var:-$'\\a'}"
\a # ok
$ echo "${var:-'\a'}"
'\a' # wtf?
Interestingly, $' '
quotes work normally, while ' '
don't. Single quotes start working correctly if the variable itself is not quoted:
$ echo ${var:-'\a'}
\a
But, that can lead to other issues if $var
itself contains whitespace characters.
Is there any good reason for this inconsistency?
I think this is the most relevant quote from the source code (y.tab.c
):
/* Based on which dolstate is currently in (param, op, or word),
decide what the op is. We're really only concerned if it's % or
#, so we can turn on a flag that says whether or not we should
treat single quotes as special when inside a double-quoted
${...}. This logic must agree with subst.c:extract_dollar_brace_string
since they share the same defines. */
/* FLAG POSIX INTERP 221 */
[...]
/* The big hammer. Single quotes aren't special in double quotes. The
problem is that Posix used to say the single quotes are semi-special:
within a double-quoted ${...} construct "an even number of
unescaped double-quotes or single-quotes, if any, shall occur." */
/* This was changed in Austin Group Interp 221 */
It's not exactly clear to me why single quotes aren't special, but it seems like a conscious choice made after long (and I've been told contentious) debate preceding the change. But the fact is (if I am summarizing this correctly), single quotes here are just regular characters, not syntactic quotes, and are treated literally.