¿Se han desaprobado los backticks (es decir, `cmd`) en * sh shells?


118

He visto este comentario muchas veces en Unix y Linux, así como en otros sitios que usan la frase "se han desaprobado los" backticks ", con respecto a los shells como Bash y Zsh.

¿Es esta declaración verdadera o falsa?


Vea Por qué no las comillas invertidas en un script de shell me ayudan cda un directorio para ver un ejemplo de por qué la $(...)notación es más fácil de usar que las comillas invertidas anidadas.
Jonathan Leffler


1
Al menos un Unix, AIX, ha documentado que los backticks son obsoletos . "Aunque ksh acepta la sintaxis de las comillas inversas, los estándares POSIX y X de Open Guidebility Issue 4 y los estándares POSIX lo consideran obsoleto. Estos estándares recomiendan que las aplicaciones portátiles usen la sintaxis $ (comando)". ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Christopher

Tengo una diferencia definitiva en "GNU bash, versión 3.2.57 (1) -release (x86_64-apple-darwin14)" en mac 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )funciona, matchingLines= backtick the same stuff backtickno funciona, parece perder la barra invertida en la barra invertida-dólar. (No es mi guión ...)
denis

Respuestas:


126

Hay dos significados diferentes de "obsoleto".

ser obsoleto: (principalmente de una función de software) ser utilizable pero considerado obsoleto y mejor evitarlo, generalmente debido a que ha sido reemplazado.

—Nuevo diccionario Oxford de América

Por esta definición, los backticks están en desuso.

El estado en desuso también puede indicar que la función se eliminará en el futuro.

- Wikipedia

Según esta definición, los backticks no están en desuso.

Aún compatible:

Citando la especificación de grupo abierto en los idiomas de comando de Shell , específicamente en la sección "2.6.3 Sustitución de comando", se puede ver que ambas formas de sustitución de comando, backticks ( `..cmd..`) o dólar parens ( $(..cmd..)) todavía son compatibles en la medida en que la especificación avanza.

extracto

La sustitución de comandos permite sustituir la salida de un comando en lugar del nombre del comando en sí. La sustitución del comando ocurrirá cuando el comando esté encerrado de la siguiente manera:

          $(command)

          or (backquoted version):

          `command`

El shell expandirá la sustitución del comando ejecutando el comando en un entorno de subshell (consulte Entorno de ejecución de Shell) y reemplazando la sustitución del comando (el texto del comando más el $()cierre o las comillas) con la salida estándar del comando, eliminando secuencias de uno o más <línea nueva> caracteres al final de la sustitución. Los caracteres <nueva línea> incrustados antes del final de la salida no se eliminarán; sin embargo, pueden tratarse como delimitadores de campo y eliminarse durante la división de campo, según el valor de IFS y las cotizaciones vigentes. Si la salida contiene bytes nulos, el comportamiento no se especifica.

Dentro del estilo de sustitución de comando entre comillas, <backslash> mantendrá su significado literal, excepto cuando sea seguido por: '$', ' \`' o <backslash> . La búsqueda de la cita inversa coincidente deberá ser satisfecha por la primera cita inversa no escapada sin comillas; durante esta búsqueda, si se encuentra una comilla inversa no escapada dentro de un comentario de shell, un documento aquí, una sustitución de comando incrustada del $(command)formulario o una cadena entre comillas, se producen resultados indefinidos. Una cadena entre comillas simples o dobles que comienza, pero no termina, dentro de la `...`secuencia " " produce resultados indefinidos.

Con el $(command)formulario, todos los caracteres que siguen el paréntesis abierto al paréntesis de cierre coincidente constituyen el comando. Se puede usar cualquier script de shell válido para el comando, excepto un script que consista únicamente en redirecciones que produzca resultados no especificados.

Entonces, ¿por qué todos dicen que los backticks han quedado en desuso?

Debido a que la mayoría de los casos de uso deberían estar haciendo uso de la forma de parens en dólares en lugar de backticks. (Desaprobado en el primer sentido anterior.) Muchos de los sitios más acreditados (incluido U&L) a menudo también lo afirman, por lo que es un buen consejo. Este consejo no debe confundirse con un plan inexistente para eliminar el soporte para backticks de los depósitos.

  • BashFAQ # 082 - ¿Por qué se prefiere $ (...) sobre `` `(backticks)?

    extracto

    `...`es la sintaxis heredada requerida solo por las capas de bourne más antiguas no compatibles con POSIX. Hay varias razones para preferir siempre la $(...)sintaxis:

    ...

  • Bash Hackers Wiki - Sintaxis obsoleta y obsoleta

    extracto

    Esta es la forma más antigua compatible con Bourne de la sustitución de comandos . POSIX especifica tanto la sintaxis `COMMANDS`como la $(COMMANDS)sintaxis, pero esta última es muy preferida, aunque lamentablemente la primera sigue siendo muy frecuente en los scripts. Las sustituciones de comandos de nuevo estilo son ampliamente implementadas por cada shell moderno (y luego algunos). La única razón para usar backticks es la compatibilidad con un shell Bourne real (como Heirloom). Las sustituciones de comandos de retroceso requieren un escape especial cuando se anidan, y los ejemplos que se encuentran en la naturaleza se citan incorrectamente la mayoría de las veces. Ver: ¿Por qué se prefiere $ (...) sobre `` `(backticks)? .

  • Fundamento estándar POSIX

    extracto

    Debido a estos comportamientos inconsistentes, la variedad de sustitución de comandos entre comillas no se recomienda para nuevas aplicaciones que anidan sustituciones de comandos o intenten incrustar scripts complejos.

NOTA: Este tercer extracto (arriba) muestra varias situaciones en las que los backticks simplemente no funcionan, pero el nuevo método parens en dólares sí, comenzando con el siguiente párrafo:

Además, la sintaxis entre comillas tiene restricciones históricas sobre el contenido del comando incrustado. Mientras que el nuevo formulario "$ ()" puede procesar cualquier tipo de secuencia de comandos incrustada válida, la forma de comillas invertidas no puede manejar algunas secuencias de comandos válidas que incluyen comillas inversas.

Si continúa leyendo esa sección, las fallas se resaltan y muestran cómo fallarían usando backticks, pero trabaje usando la nueva notación de parens en dólares.

Conclusiones

Por lo tanto, es preferible que use parens en dólares en lugar de backticks, pero en realidad no está usando algo que ha sido técnicamente "desaprobado" como en "esto dejará de funcionar por completo en algún punto planificado".

Después de leer todo esto, debe tener la idea de que le recomendamos encarecidamente que use parens en dólares a menos que requiera específicamente compatibilidad con un shell Bourne original que no sea POSIX.


26
Según la mayoría de los significados de obsoleto , yo (y usted) diría que los backticks son obsoletos. Es sobre todo una cuestión de terminología.
Stéphane Chazelas

44
@StephaneChazelas - ¡De acuerdo! Continuaré diciéndole a ppl que están en desuso pero que los backticks no han sido oficialmente "en desuso" en el sentido de que serán eliminados activamente de la base de código de cualquier shell en el futuro cercano. Al menos ninguno que yo sepa.
slm

3
Mi interpretación es que las comillas inversas son compatibles únicamente porque están demasiado arraigadas en el código existente para desaprobarlas formalmente. Nunca he escuchado un argumento para continuar usándolos en un nuevo código.
chepner

3
@slm Sí, supongo que lo entendiste, me alejaron y no me di cuenta. Casi no hay razón para usar estas cosas, excepto que puede ser un poco más limpio cuando se superponen capas, por lo que $( cmd `cmd`)es un poco menos complicado que $( cmd $(cmd)): es más fácil de leer. Siempre he considerado que una característica obsoleta en el software es una marca oficialmente marcada para su eliminación aguas arriba, y nunca he oído hablar de algo así. No me importa, no tengo amor por la tumba.
mikeserv

3
Es posible que desee agregar la siguiente cita del razonamiento estándar de POSIX : Debido a estos comportamientos inconsistentes, la variedad de sustitución de comandos entre comillas no se recomienda para nuevas aplicaciones que anidan sustituciones de comandos o intenten incrustar scripts complejos. Si bien esto no es una depreciación formal ya que la sección de justificación es informativa y no normativa, sugiere que se debe evitar el uso continuo de backticks.
jw013

15

No está en desuso, pero el backticks ( `...`) es la sintaxis heredada requerida solo por la más antigua de las cáscaras de bourne no compatibles con POSIX y $(...)es POSIX y más preferida por varias razones:

  • Las barras invertidas ( \) dentro de los backticks se manejan de una manera no obvia:

    $ echo "`echo \\a`" "$(echo \\a)"
    a \a
    $ echo "`echo \\\\a`" "$(echo \\\\a)"
    \a \\a
    # Note that this is true for *single quotes* too!
    $ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar" 
    foo is \, bar is \\
  • Las citas anidadas en el interior $()son mucho más convenientes:

    echo "x is $(sed ... <<<"$y")"

    en lugar de:

    echo "x is `sed ... <<<\"$y\"`"

    o escribiendo algo como:

    IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`

    porque $()usa un contexto completamente nuevo para citar

    que no es portátil ya que los shells Bourne y Korn requerirían estas barras invertidas, mientras que Bash y dash no.

  • La sintaxis para las sustituciones de comandos de anidación es más fácil:

    x=$(grep "$(dirname "$path")" file)

    que:

    x=`grep "\`dirname \"$path\"\`" file`

    porque $()impone un contexto completamente nuevo para las citas, por lo que cada sustitución de comandos está protegida y puede tratarse por sí sola sin especial preocupación por las citas y las escapadas. Al usar backticks, se vuelve más y más feo después de dos niveles o más.

    Pocos ejemplos más:

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
  • Resuelve un problema de comportamiento inconsistente cuando se usan comillas inversas:

    • echo '\$x' salidas \$x
    • echo `echo '\$x'` salidas $x
    • echo $(echo '\$x') salidas \$x
  • La sintaxis de Backticks tiene restricciones históricas sobre el contenido del comando incrustado y no puede manejar algunos scripts válidos que incluyen comillas inversas, mientras que el $()formulario más nuevo puede procesar cualquier tipo de script incrustado válido.

    Por ejemplo, estos scripts incrustados válidos de otro modo no funcionan en la columna izquierda, pero sí funcionan en el IEEE derecho :

    echo `                         echo $(
    cat <<\eof                     cat <<\eof
    a here-doc with `              a here-doc with )
    eof                            eof
    `                              )
    
    
    echo `                         echo $(
    echo abc # a comment with `    echo abc # a comment with )
    `                              )
    
    
    echo `                         echo $(
    echo '`'                       echo ')'
    `                              )

Por lo tanto, la sintaxis para la $sustitución de comandos prefijada debería ser el método preferido, ya que es visualmente clara con una sintaxis limpia (mejora la legibilidad humana y mecánica), es anidable e intuitiva, su análisis interno es independiente y también es más consistente (con todas las demás expansiones que se analizan entre comillas dobles) donde los backticks son la única excepción y el `carácter se camufla fácilmente cuando está adyacente para "hacerlo aún más difícil de leer, especialmente con fuentes pequeñas o inusuales.

Fuente: ¿Por qué se $(...)prefiere `...`(backticks)? en BashFAQ

Ver también:

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.