Mónica, miembro de este gran staff, nos hizo el favor de crear este tutorial ya que conoce perfectamente este tema.
Solución:
'$
no significa nada especial. Con %d
en printf
intenta evaluar el argumento como una expresión entera. 'a
se toma como el char
a
o el entero 97. Obtendría el mismo resultado incluso si no usara la expansión variable:
$ printf %d\n "'a'"
97
$ printf %d\n "'0'"
48
$ printf %d\n "'"$'1'
1
De la documentación de bash en printf
(énfasis mío):
Argumentos para nostring los especificadores de formato se tratan como constantes del lenguaje C, excepto que se permite un signo más o menos inicial, y si el carácter inicial es una comilla simple o doble, el valor es el valor ASCII del carácter siguiente.
Los caracteres restantes se ignoran, como se indica en los comentarios.
los '
es parte del argumento printf (consulte la sección Argumentos aquí).
los $
es parte de la expansión regular de shell, por lo que el printf
los argumentos se convierten %d
y 'a
.
Finalmente, $(...)
construcción es sustitución de comando, lo que en este caso significa que NUM
tiene su valor establecido en la salida del printf
función.
Como ya se dijo, el '$
no significa nada especial por sí mismo. Tu "'$VAR"
se expande a 'a
que se pasará como argumento a la printf
utilidad.
Luego viene la parte interesante: una característica oscura pero estándar de printf
(la utilidad de shell, no la función del lenguaje C).
Según el estándar SuSv4 (énfasis mío):
Los operandos del argumento [to
printf
] se tratarán como cadenas si el especificador de conversión correspondiente esb
,c
os
y será evaluado como si fuera por elstrtod()
función si el especificador de conversión correspondiente esa
,A
,e
,E
,f
,F
,g
oG
.De lo contrario [e.g. if the conversion specifier is
d
]se evaluarán como constantes enteras C sin sufijo, como se describe en la norma ISO C, con las siguientes extensiones:
Un liderazgo
o
será permitido.
Si el personaje principal es un comillas simples o comillas doblesel valor será el valor numérico en el conjunto de códigos subyacente del personaje que sigue al comillas simples o comillas dobles.
- Se pueden permitir constantes enteras con sufijo.
Si su shell admite caracteres multibyte (como con UTF-8, el valor predeterminado en cualquier sistema moderno), ese valor numérico será el del carácter completo, no el del byte principal:
% printf '%dn' '"á' "'é"
225
233
% printf 'U+%Xn' '"猫儿'
U+732B
Tenga en cuenta que ese no es el “valor ASCII” del carácter: la descripción de la página de manual de bash es, en el mejor de los casos, engañosa.
Sin embargo, bash (y la mayoría de los otros shells excepto yash) no cumplen con el estándar, porque realizarán esa traducción incluso con especificadores flotantes como f
o g
lo que es una clara violación del primer párrafo anterior, que dice que strtod()
debe usarse en ese caso:
% bash --posix -c 'printf "%fn" "Q'
81.000000
Sección de Reseñas y Valoraciones
Más adelante puedes encontrar las acotaciones de otros programadores, tú todavía tienes la libertad de insertar el tuyo si te apetece.