2012-02-23 10 views
134

¿Cuál es la forma preferida de hacer sustitución de comandos en bash?Sustitución de comandos: ¿se incluyen los palos de fondo o el signo de dólar/paren?

que siempre he hecho de esta manera:

echo "Hello, `whoami`." 

Sin embargo, recientemente, a menudo he visto escrito así:

echo "Hello, $(whoami)." 

¿Cuál es la sintaxis preferida y por qué? ¿O son más o menos intercambiables?

Tiendo a favorecer al primero, simplemente porque mi editor de texto parece saber de qué se trata, y resalta correctamente la sintaxis.

Leo here que los caracteres que escapan actúan de forma un poco diferente en cada caso, pero no está claro para mí qué comportamiento es preferible, o si solo depende de la situación.

Pregunta lateral: ¿Es una mala práctica usar ambos formularios en una secuencia de comandos, por ejemplo, al anidar sustituciones de comandos?

+1

Como nota al margen: el ejemplo no funciona :) Debe usar: echo "Hello, $ (whoami)" '!' (debido al uso del signo de exclamación) – rmuller

+0

@rmuller, eso es lo que obtengo por no probar ejemplos. Cambió a un período. :) –

Respuesta

136

Hay varias preguntas/cuestiones aquí, así que voy a repetir cada sección del texto del cartel , citado en bloque y seguido por mi respuesta.

¿Cuál es la sintaxis preferida, y por qué? ¿O son más o menos intercambiables?

Yo diría que se prefiere el formulario $(some_command) sobre el formulario `some_command`. La segunda forma, usando un par de comillas inversas (el caracter "` ", también llamado retroceso y acento grave), es la forma histórica de hacerlo. El primer formulario, con signo de dólar y paréntesis, es un formulario POSIX más nuevo, lo que significa que probablemente sea una forma más estándar de hacerlo. A su vez, creo que eso significa que es más probable que funcione correctamente con diferentes shells y con diferentes implementaciones de * nix.

Otra razón para preferir la primera forma (POSIX) es que es más fácil de leer, especialmente cuando se anidan las sustituciones de comandos. Además, con la forma de retroceso, los caracteres de retroceso deben tener una barra invertida escapada en las sustituciones de los comandos anidados (internos).

Con el formulario POSIX, no necesita hacer eso.

En cuanto a si son intercambiables, bueno, yo diría que, en general, son intercambiables, aparte de las excepciones que mencionas para los caracteres escapados. Sin embargo, no sé y no puedo decir si todas las conchas modernas y todas las modernas * nix son compatibles con ambas formas. Dudo que lo hagan, especialmente conchas viejas/viejos * nixes. Si yo fuera usted, no dependería de la intercambiabilidad sin antes realizar un par de pruebas rápidas y simples de cada formulario en cualquier implementación shell/* nix en la que planee ejecutar sus scripts terminados.

Tiendo a favorecer al primero, simplemente porque mi editor de texto parece saber de qué se trata, y resalta correctamente la sintaxis.

Desafortunadamente, su editor no parece ser compatible con el formulario POSIX; tal vez deba verificar si hay alguna actualización para su editor que admita la forma POSIX de hacerlo. Posiblemente un tiro lejano, pero ¿quién sabe? O quizás deberías considerar probar un editor diferente.

GGG, ¿qué editor de texto estás usando ???

He leído aquí que los caracteres que escapan actúan de forma diferente en cada caso, pero no está claro para mí qué comportamiento es preferible, o si solo depende de la situación.

Yo diría que depende de lo que está tratando de lograr; en otras palabras, si está usando caracteres escapados junto con la sustitución de comandos o no.

Pregunta lateral: ¿Es una mala práctica usar ambas formas en una secuencia de comandos, por ejemplo, al anidar sustituciones de comandos?

Bueno, podría hacer que el guión fuera ligeramente más fácil de LEER (tipográficamente hablando), ¡pero más difícil de ENTENDER! Alguien que lea su guión (¡o USTED, leyéndolo seis meses después!) Probablemente se pregunte por qué no se limitó a apegarse a una u otra forma, a menos que ponga algún tipo de nota sobre por qué lo hizo en los comentarios. Además, mezclar ambas formas en una secuencia de comandos haría que esa secuencia de comandos sea menos portátil: para que la secuencia de comandos funcione correctamente, el intérprete de comandos que la ejecuta debe admitir AMBOS formularios, no solo una forma u otra.

Para hacer comprensible un guión de shell, personalmente prefiero apegarme a una forma u otra a través de cualquier guión, a menos que haya una buena razón técnica para hacer lo contrario. Además, preferiría el formulario POSIX sobre el formulario anterior; nuevamente, a menos que haya una buena razón técnica para hacer lo contrario.

Para obtener más información sobre el tema de sustitución de comandos y las dos formas diferentes de hacerlo, le sugiero que consulte la sección sobre sustitución de comandos en el libro de O'Reilly "Classic Shell Scripting", segunda edición, por Robbins y Beebe. En esa sección, los autores afirman que el formulario POSIX para la sustitución de comandos "se recomienda para todos los nuevos desarrollos". No tengo ningún interés financiero en este libro; es solo una que tengo (y amo) en las secuencias de comandos del shell, aunque es más para scripts de shell intermedio o avanzado, y no realmente para el inicio de scripts de shell.

-B.

+5

Guau ... Estoy impresionado por la minuciosidad de esta respuesta. Usualmente uso gedit para cosas cotidianas; Enderece las cosas entre las comillas posteriores. –

+5

Buena respuesta general: definitivamente se prefieren los paréntesis. Pero tenga en cuenta que backticks * es * parte del estándar POSIX. La forma en que la respuesta se formatea incorrectamente implica que no lo es. – zaTricky

+0

Tenía curiosidad acerca de la fuente de la declaración "La primera forma, usando signo de dólar y paréntesis, es una forma POSIX más nueva", así que aquí está [la especificación POSIX sobre ella] (http://pubs.opengroup.org/onlinepubs) /9699919799/utilities/V3_chap02.html#tag_18_06_03). –

39

Puede leer las diferencias de bash manual. En la mayoría de los casos, son intercambiables.


Una cosa a mencionar es que debes escapar backquote a los comandos de nido:

$ echo $(echo hello $(echo word)) 
hello word  

$ echo `echo hello \`echo word\`` 
hello word 

+11

Se vuelve * realmente * feo cuando tienes un tercer nivel de anidación con palos de retroceso. Simplemente quédese con el formulario '$()' –

+4

Por esta razón, a menudo utilizo backticks para el primer nivel y '$()' para más anidación. – Kevin

+0

@Kevin eso es lo que he estado haciendo últimamente, pero después de ver la respuesta de Bruce siento que debería cambiar :) –

8

Los backticks son compatibles con shells antiguos, por lo que los scripts que deben ser portátiles (como los fragmentos de autoconf de GNU) deberían preferirlos.

La forma $() es un poco más fácil para los ojos, esp. después de algunos niveles de escape.

+0

"después de algunos niveles de escape" ... ¿cómo se puede escapar del segundo nivel de backticks? \\\ '? Nunca he estado tan lejos en el agujero del conejo, supongo;) –

+6

El truco es darse cuenta de que las barras traseras deben escaparse: 'echo \' echo \\ 'echo \\\\' pwd \\\\ ' \\ '\' ' – phs

Cuestiones relacionadas