Entender el backtick (`)

35

Estoy probando el comando

$ b=5; echo `$b`;
-bash: 5: command not found

pero no imprime 5 como se supone que debe hacerlo. ¿Que me estoy perdiendo aqui?

¿Qué significa `(backquote / backtick) en los comandos? parece decir que `evalúa los comandos dentro y los reemplaza con la salida.

coolcric
fuente
8
Tenga en cuenta que no se recomiendan los backticks, ya que perderá la capacidad de realizar sustituciones de ejecución anidadas. Insetad, $ (algún comando) es el preferido. En mi opinión, mejora la legibilidad.
Tommy
66
@Tommy, No, los backticks pueden anidarse, pero se convierte en una pesadilla que se escapa, especialmente cuando también se hace doble cita.
Stéphane Chazelas

Respuestas:

52

El texto entre comillas invertidas se ejecuta y se reemplaza por la salida del comando (menos los caracteres de línea nueva finales, y tenga en cuenta que los comportamientos de shell varían cuando hay caracteres NUL en la salida). Eso se llama sustitución de comando porque se sustituye con la salida del comando. Entonces, si desea imprimir 5, no puede usar comillas invertidas, puede usar comillas, como echo "$b"o simplemente dejar cualquier cita y usar echo $b.

Como puede ver, dado que $bcontiene 5, cuando usa backticks bashestá intentando ejecutar el comando 5y dado que no existe dicho comando, falla con el mensaje de error.

Para entender cómo funcionan los backticks, intente ejecutar esto:

$ A=`cat /etc/passwd | head -n1`
$ echo "$A"

cat /etc/passwd |head -n1debería imprimir la primera línea del /etc/passwdarchivo. Pero como usamos backticks, no imprime esto en la consola. En cambio, se almacena en Avariable. Puedes hacer eco $Ade esto. Tenga en cuenta que una forma más eficiente de imprimir la primera línea es mediante el comando, head -n1 /etc/passwdpero quería señalar que la expresión dentro de los backticks no tiene que ser simple.

Entonces, si la primera línea de / etc / passwd es root:x:0:0:root:/root:/bin/bash, el primer comando será sustituido dinámicamente por bash to A="root:x:0:0:root:/root:/bin/bash".

Tenga en cuenta que esta sintaxis es del shell Bourne. Citar y escapar se convierte rápidamente en una pesadilla, especialmente cuando comienzas a anidarlos. Ksh introdujo la $(...)alternativa que ahora está estandarizada ( POSIX ) y es compatible con todos los shells (incluso el shell Bourne de Unix v9). Por lo tanto, debe usar $(...)en su lugar hoy en día a menos que necesite ser portátil para conchas Bourne muy antiguas.

También tenga en cuenta que la salida de `...`y $(...)está sujeta a la división de palabras y la generación de nombre de archivo al igual que la expansión de variables (en zsh, división de palabras solamente), por lo que generalmente debería citarse en contextos de lista.

Krzysztof Adamski
fuente
1
Hola @Krzysztof, ¡eso es útil! "dado que $ b contiene 5, bash está intentando ejecutar el comando 5" es exactamente lo que estaba buscando
coolcric
you can use quotation marks, like echo "$b"=> ¿el "" hace algo especial? Parece echo $bque funcionaría igual de bien.
Tootsie Rolls
@Anita: En general, las comillas hacen algunas cosas especiales (cambia la forma en que se tratan los caracteres especiales, especialmente los espacios en blanco), pero en este caso, se pueden quitar sin muchos problemas. Esto se debe a que no se utilizan caracteres especiales y al echocomando no le importa la cantidad de argumentos que obtiene, por lo que si btiene algunos espacios en el interior, obtendrá múltiples argumentos y aún los imprimirá. Este puede no ser el caso para otros comandos (especialmente cuando la variable no está configurada), por lo que siempre tiendo a rodear las variables con comillas.
Krzysztof Adamski
Sería bueno si (POSIX)fuera un enlace al estándar real.
erikbwork
1
@ erikb85: Esta nota no fue agregada por mí, pero la edité con el enlace que sugirió :)
Krzysztof Adamski
11

El backtick hace exactamente lo que tú dices. Ha establecido una variable en un entero. Cuando colocas esa variable dentro de los backticks, bash intentará ejecutarla como un comando. Como no es un comando, obtienes el error que viste.

Lo que quieres hacer es simplemente:

$ b=5; echo $b

Para comprender mejor los backticks, compare con:

$ b=5; a=`echo $b`; echo $a
  5
terdon
fuente
8

Ir paso a paso su línea debería explicarlo.

$ b=5; echo `$b`;
  1. establece variable ba 5
  2. evalúa $b(ejecuta efectivamente 5)
  3. echoes el resultado de la evaluación anterior.

Entonces sí, se espera la salida que obtuviste. Estás evaluando el contenido de una variable, no el comando real que creías que eras. Todo lo que pones dentro de los backticks se evalúa (ejecuta) en un nuevo (sub) shell.

gertvdijk
fuente
hola @gertvdijk, ¡gracias por tu publicación! Estaba pensando que `devuelve todo lo que queda después de evaluar su contenido. Entonces, pensé que '$ b' habría devuelto 5 para echo para imprimirlo
coolcric