As already said, the '$
doesn't mean anything special by itself. Your "'$VAR"
gets expanded to 'a
, which will be passed as an argument to the printf
utility.
Then come the interesting part -- an obscure, but standard feature of printf
(the shell utility, not the function from the C language).
According to the SuSv4 standard (emphasis mine):
The argument operands [to printf
] shall be treated as strings if the
corresponding conversion specifier is b
, c
, or s
, and shall be
evaluated as if by the strtod()
function if the corresponding
conversion specifier is a
, A
, e
, E
, f
, F
, g
, or G
.
Otherwise [e.g. if the conversion specifier is d
], they
shall be evaluated as unsuffixed C integer constants, as described
by the ISO C standard, with the following extensions:
A leading <plus-sign>
or <hyphen-minus>
shall be allowed.
If the leading character is a single-quote or double-quote, the
value shall be the numeric value in the underlying codeset of the
character following the single-quote or double-quote.
- Suffixed integer constants may be allowed.
If your shell supports multibyte characters (as with UTF-8, the default on any modern system), that numeric value will be that of the complete character, not of its leading byte:
% printf '%d\n' '"á' "'é"
225
233
% printf 'U+%X\n' '"猫儿'
U+732B
Notice that that's not the "ASCII value" of the character -- the description for the bash manpage is at best misleading.
However, bash (and most other shells but yash) are not standard conformant, because they will perform that translation even with float specifiers like f
or g
, which is in clear violation of the first paragraph above, which says that strtod()
should be used in that case:
% bash --posix -c 'printf "%f\n" \"Q'
81.000000
printf "%d" "'a"
and see what happensprintf -v NUM "%d" "'$VAR"
without having to spawn a subshell.