2011-01-16 20 views
178

En sh/ksh/bash para almacenar la salida de un comando como una variable que puede hacer ya sea

MY_VAR=$(command) 
#or you can do 
MY_VAR=`command` 

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

+21

Consulte [BashFAQ/082] (http://mywiki.wooledge.org/BashFAQ/082). –

+0

Encontrará el problema anidado detallado en la Guía de codificación de Git: vea [mi respuesta a continuación] (http://stackoverflow.com/a/24592916/6309). – VonC

Respuesta

199

Los backticks/gravemarks han quedado en desuso en favor de $() para la sustitución de comandos porque $() puede anidar fácilmente dentro de sí mismo como en $(echo foo$(echo bar)). Existen otras diferencias, como la forma en que se analizan las barras invertidas en la versión backtick/gravemark, etc.

Consulte 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.

+20

Buen enlace, pero ese texto no _deprecata_ las comillas inversas a favor de '$ (...)' - simplemente las nota como alternativas. –

+19

@NormanGray POSIX no puede decir la palabra * * obsoleta pero sí decir ' "No se recomienda la variedad backquoted de sustitución de comandos"' que es sólo una forma prolija de decir obsoleta en mi humilde opinión – SiegeX

+7

POSIX no despreciar acentos abiertos, sino más bien añadió '$ (...)' como un método alternativo. No se conoce ningún error de implementación con backticks, pero existen muchos errores de implementación conocidos con '$ (...)'. Por lo tanto, para problemas de portabilidad, se recomienda el uso de backticks para llamadas no anidadas. '$ (...)' necesita un analizador recursivo, pero esto no se usó con ksh86 que introdujo la característica. Consulte http://www.in-ulm.de/~mascheck/various/cmd-subst/ para obtener una lista de las implementaciones correctas. Un caparazón conforme debe soportar todos los casos, excepto el caso D.2. – schily

5

Hay poca diferencia, a excepción de los caracteres no escamados que puede usar dentro del comando. Incluso puede poner `...` comandos dentro de unos (...) unos (y viceversa) para una sustitución de comando de dos niveles más complicada.

Hay una interpretación ligeramente diferente del carácter/operador de barra diagonal inversa. Entre otras cosas, cuando se anidan `` comandos ... de sustitución, debe escapar de los interiores ` caracteres con \, mientras que con$() SUSTITUCIÓN se entiende la anidación de forma automática.

22

Cuando se usa la forma más antigua de la marca de retroceso, la barra invertida conserva su significado literal, excepto cuando está seguido de $, `, o \. La primera marca de retroceso no precedida de una barra invertida termina la sustitución del comando.

Al usar el formulario $(command) más reciente, todos los caracteres entre paréntesis componen el comando; ninguno es tratado especialmente.

Ambas formas se pueden anidar, pero la variedad de la marca de retroceso requiere la siguiente forma.

`echo \`foo\`` 

A diferencia:

$(echo $(foo)) 
+1

Corrección secundaria, tanto la versión de retroceso como la de '$()' son compatibles con POSIX. – SiegeX

+0

Observado y actualizado, gracias. – ocodo

32

se comportan de la misma. La diferencia es sintáctica: es más fácil para anidar $() de ``:

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

vs

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

'echo $ (echo \ $ abc)' no es lo mismo que '' echo 'echo \ $ abc''' - También existen diferencias para' '$ (echo \') '' y '' $ (echo \ \) '' –

22

de julio de 2014: El commit f25f5e6 (por Elia Pinto (devzero2000), abril de 2014, Git 2.0) se suma a la cuestión de anidación:

La forma backquoted es el método tradicional para la sustitución de comandos, y es compatible con POSIX.
Sin embargo, todos los usos más simples se complican rápidamente.
En particular, las sustituciones de comandos incrustadas y/o el uso de comillas dobles requieren escapes cuidadosos con el carácter de barra diagonal inversa
.

Por eso, el git/Documentation/CodingGuidelines menciones:

Preferimos $(...) para 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.

thitoncommented:

Por eso `echo `foo`` no va a funcionar, en general, debido a la ambigüedad inherente debido a que cada `` puede apertura o cierre.
Podría funcionar para casos especiales debido a la suerte o características especiales.


actualización de enero de 2016: Git 2.8 (marzo de 2016) se deshace de acentos abiertos en su totalidad.

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

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

+1

@VonC nota para mí: esta es mi medalla n. ° 150 del Nigromante. – VonC

+0

'$()' también está especificado por POSIX, una cita que describe los backticks como "POSIX-supported" de tal manera que implica que esto es exclusivo para ellos es engañoso. Es solo (de la década de 1970) pre-POSIX Bourne donde los respaldos son la única sintaxis admitida. –

Cuestiones relacionadas