¿Cuál es la diferencia entre $ (cosas) y `cosas`?

265

Hay dos sintaxis para la sustitución de comandos: con paréntesis en dólares y con comillas invertidas. Ejecutando top -p $(pidof init)y top -p `pidof init`da la misma salida. ¿Son estas dos formas de hacer lo mismo o hay diferencias?

tshepang
fuente
18
Ver también: BashFAQ / 082 .
Dennis Williamson el
43
Por un segundo, pensé que era una pregunta de jQuery.
David Murdoch
El resultado puede depender del shell, algunos admiten ambos.
artdanil

Respuestas:

360

Las comillas inversas de estilo antiguo ` `tratan las barras diagonales inversas y la anidación un poco diferente. El nuevo estilo $()interpreta todo en el medio ( )como un comando.

echo $(uname | $(echo cat))
Linux

echo `uname | `echo cat``
bash: command substitution: line 2: syntax error: unexpected end of file
echo cat

funciona si se escapan las comillas inversas anidadas:

echo `uname | \`echo cat\``
Linux

diversión de barra invertida:

echo $(echo '\\')
\\

echo `echo '\\'`
\

El nuevo estilo se $()aplica a todos los shells conformes con POSIX .
Como señaló Mouviciel , el estilo antiguo ` `podría ser necesario para las conchas más antiguas.

Además del punto de vista técnico, el estilo antiguo ` `también tiene una desventaja visual:

  • Difícil de notar: I like $(program) better than `program`
  • Fácilmente confundido con una sola cita: '`'`''`''`'`''`'
  • No es tan fácil de escribir (tal vez ni siquiera en el diseño estándar del teclado)

(y SE lo usa ` `para su propio propósito, fue un dolor escribir esta respuesta :)

meneo
fuente
10
Lo único que agregaría es que llamo '(' un par, no un paréntesis (que es '[').
Kendall Helmstetter Gelner
@Kendall: y aquí pensé que '{' era el soporte izquierdo para todos esos años ...
SamB
55
@Sam: { }generalmente se llama "llaves" o "llaves" en.wikipedia.org/wiki/Braces_(punctuation)#Braces
Jørn Schou-Rode
2
También me refiero a '{' como llaves. Aunque parezca extraño, debe agregar el calificador "rizado" si llama a las otras cosas entre paréntesis ... Supongo que es solo porque realmente se curvan.
Kendall Helmstetter Gelner
1
@slim No lo sé en los teclados de EE. UU./Reino Unido, pero en los teclados en español `es una tecla muerta, por lo que tengo que escribir un doble retroceso (algo que generalmente olvido que incluso puedo hacer) o retroceder y luego el espacio, que es un dolor.
Darkhogg
41

La diferencia obvia que observo es que no puedes anidar backticks mientras puedes anidar $(). Tal vez ambos existan por razones heredadas. Del mismo modo, los comandos .y sourceson sinónimos.

balki
fuente
10
Algunas conchas derivadas de Bourne no reconocen source. Dash es un ejemplo.
Dennis Williamson
14
Eso no es cierto. Puedes anidar backtick a cualquier nivel, solo que más dolorosamente. Tenga en cuenta que ambos $(...)y `...`son estándar (este último está en desuso) mientras que .es estándar pero nosource
Stéphane Chazelas
3
Corrección, solo en (t)cshno se pueden anidar. aunque (t)cshno lo soportes $(...). Sin embargo, sí admiten source(y no .).
Stéphane Chazelas
28

$()no funciona con el viejo shell Bourne. Pero han pasado años desde que trabajé con el viejo shell Bourne.

Mouviciel
fuente
Viejo como en 1970 y principios de 1980, ¿correcto?
Christopher
6

Otra nota, $()usará más recursos del sistema que usar backticks, pero es un poco más rápido.

En Mastering Unix shell scripting , Randal K. Michael había hecho una prueba en un capítulo llamado "24 formas de procesar un archivo línea por línea".

Cuonglm
fuente
2
Este reclamo no tiene sentido. No hay razón para que sea más rápido, ya que solo usa una notación diferente para el analizador.
schily
@schily: Tal vez, solo cito el libro, puedes leerlo para obtener más detalles.
Cuonglm
3
Tendería a estar de acuerdo con @schily ... ¿por qué tomaría más recursos?
Comodín
2
@Wildcard, supongo que es porque $()hace que su script sea un byte más grande que si se usara `(suponiendo que no los anide y no use barras invertidas dentro). En cuanto a cuál sería más rápido de analizar, eso variaría entre los proyectiles y sería irrelevante, ya que sería insignificante en comparación con el costo de crear una tubería y un proceso de bifurcación que implica la sustitución del comando.
Stéphane Chazelas
5

Para agregar a lo que otros dijeron aquí, puede usar los backticks para simular comentarios en línea:

echo foo `# I'm a comment!` bar

La salida es: foo bar.

Consulte lo siguiente para obtener más información: https://stackoverflow.com/a/12797512 (Tenga en cuenta también los comentarios debajo de esa publicación).

phk
fuente
1

La $()sintaxis no funcionará con el viejo shell bourne.
Con shells más nuevos ` `y $()equivalentes, pero $()es mucho más conveniente de usar cuando necesita anidar múltiples comandos.

Por ejemplo :

echo $(basename $(dirname $(dirname /var/adm/sw/save )))

es más fácil de escribir y depurar que:

echo `basename \`dirname \\\`dirname /var/adm/sw/save \\\`\``
Emmanuel
fuente
1
Si bien $ () puede verse bien, es un problema al implementar un analizador relacionado porque requiere un analizador recursivo dual.
schily
66
@schily Por otro lado, lo que sería un shell sin un buen analizador.
Emmanuel
1
El problema es que necesita saber dónde termina la cadena antes de llamar al analizador. Esto es relativamente simple con los backticks, pero es difícil con los corchetes, ya que se utilizan para diversos fines en el shell. Por lo tanto, necesita el analizador dos veces y de una manera que no existe en Bourne Shell.
schily