¿Cuál es la diferencia entre $ (comando) y `comando` en la programación de shell?


258

Para almacenar la salida de un comando como una variable en sh / ksh / bash, puede hacer cualquiera

var=$(command)

o

var=`command`

¿Cuál es la diferencia, si hay alguna, entre los dos métodos?



Encontrará el problema anidado detallado en la Guía de codificación de Git: consulte mi respuesta a continuación .
VonC

Respuestas:


274

Los acentos abiertos / gravemarks han sido desaprobados en favor de $()la sustitución de comandos porque $()puede fácilmente anidan en su interior como en $(echo foo$(echo bar)). Existen otras diferencias, como cómo se analizan las barras diagonales inversas en la versión backtick / gravemark, etc.

Vea BashFAQ / 082 por varias razones para preferir siempre la sintaxis $ (...).

Consulte también la especificación POSIX para obtener información detallada sobre las diversas diferencias.


25
Buen enlace, pero ese texto no desprecia las comillas inversas a favor $(...), solo las anota como alternativas.
Norman Gray

24
@NormanGray POSIX puede no decir la palabra en desuso, pero sí dice "the backquoted variety of command substitution is not recommended"cuál es solo una forma larga y sin aliento de decir en desuso IMHO
SiegeX

11
POSIX no desaprobó los backticks, sino que los agregó $(...)como un método alternativo. No hay errores de implementación conocidos con backticks, pero hay muchos errores de implementación conocidos $(...) . Por lo tanto, para problemas de portabilidad, se recomienda utilizar backticks para llamadas no anidadas. $(...)necesita un analizador recursivo pero esto no se usó con ksh86 que introdujo la función. Consulte en inulm.de/~mascheck/various/cmd-subst para obtener una lista de implementaciones correctas. Un shell conforme necesita soportar todos los casos excepto el caso D.2.
schily

2
Hay otras cosas en POSIX que deben considerarse deprecated, por ejemplo, el uso de waitpid()eso evita que vea los 32 bits completos del exit()parámetro, pero todos los shells, excepto el Bourne Shell reciente, todavía se usan en waitpid()lugar de la waitid()llamada que ahora está disponible desde 26 años.
schily

El enlace en la respuesta sugiere que hay algunas diferencias entre los backticks y $(), lo cual se explica más en esta parte de la documentación . Las diferencias no se trata solo de anidar.
Algún programador amigo

39

Se comportan igual. La diferencia es sintáctica: es más fácil anidar $()que ``:

listing=$(ls -l $(cat filenames.txt))

vs.

listing=`ls -l \`cat filenames.txt\``

10
echo $(echo \$abc)no es lo mismo que echo `echo \$abc`‍- También existen diferencias para $(echo \`)y $(echo \\)
Peter.O

Otra diferencia es: echo foo `#comment`vs echo foo $(#comment). El segundo no funciona. (Utilizado para comentar en un comando de varias líneas.)
wisbucky

27

Julio de 2014: El commit f25f5e6 (por Elia Pinto ( devzero2000) , abril de 2014, Git 2.0) se suma al problema de anidación:

El formulario entre comillas es el método tradicional para la sustitución de comandos, y es compatible con POSIX.
Sin embargo, todos menos los usos más simples se complican rápidamente.
En particular, las sustituciones de comandos incrustados y / o el uso de comillas dobles requieren un escape cuidadoso con el carácter de barra diagonal inversa
.

Es por eso que git / Documentation / CodingGuidelines menciona:

Preferimos la $( ... )sustitución de comandos; a diferencia de ``, anida correctamente .
Debería haber sido la forma en que Bourne lo deletreó desde el primer día, pero desafortunadamente no lo es.

thiton comentó :

Es por eso `echo `foo`` que no funcionará en general debido a la ambigüedad inherente porque cada uno ``puede abrirse o cerrarse.
Puede funcionar para casos especiales debido a la suerte o características especiales.


Actualización de enero de 2016: Git 2.8 (marzo de 2016) elimina completamente los backticks.

Ver cometer ec1b763 , comprometerse 9c10377 , comprometerse c7b793a , comprometerse 80a6b3f , comprometerse 9375dcf , comprometerse e74ef60 , comprometerse 27fe43e , comprometerse 2525c51 , comprometerse becd67f , comprometerse a5c98ac , comprometerse 8c311f9 , comprometerse 57da049 , comprometerse 1d9e86f , comprometerse 78ba28d , comprometerse efa639f , ) . (Fusionada por comprometerse 1be2fa0 , cometen 38e9476 , commit 8823d2f , commit 32858a0 , commit cd914d8(12 de enero de 2016) por Elia Pinto (devzero2000 Junio ​​C Hamano - - en commit e572fef , 22 de enero de 2016)
gitster

Desde Git 2.8 en adelante, es todo $(...), no más `...`.


2
$()también está especificado por POSIX: una cita que describe los backticks como "compatibles con POSIX" de tal manera que implica que esto es exclusivo para ellos es engañoso. Es solo Bourne pre-POSIX (era de la década de 1970) donde los backticks son la única sintaxis compatible.
Charles Duffy

25

Cuando se usa la forma anterior de retroceso, la barra diagonal inversa conserva su significado literal, excepto cuando va seguida de $, `o \. La primera marca de retroceso no precedida por una barra invertida termina la sustitución del comando.

Cuando se usa la $(command)forma más nueva , todos los caracteres entre paréntesis forman el comando; ninguno es tratado especialmente.

Ambas formas se pueden anidar, pero la variedad de back-tick requiere la siguiente forma.

`echo \`foo\`` 

Opuesto a:

$(echo $(foo))

1
Corrección menor, tanto la versión de backtick como la $()versión son compatibles con POSIX.
SiegeX

5

Hay poca diferencia, excepto por los caracteres sin escape que puede usar dentro del comando. Incluso puede poner los comandos `...` dentro de $ (...) unos (y viceversa) para una sustitución de comandos de dos niveles más complicada.

Hay una interpretación ligeramente diferente del carácter / operador de barra diagonal inversa. Entre otras cosas, al anidar los comandos de sustitución `...` , debe escapar de los caracteres ` internos con \, mientras que con la substión $ () entiende el anidamiento automáticamente.


0

"¿Cuál es la diferencia, si hay alguna, entre los dos métodos?"

Presta atención a este comportamiento:

A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"

Obtendrá estos resultados:

$A
A_VARIABLE

 

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.