Cómo anidar correctamente las comillas inversas de Bash

92

O me perdí un poco de reacción o la reacción no parece funcionar con demasiados bucles de citas del programador.

$ echo "hello1-`echo hello2-\`echo hello3-\`echo hello4\`\``"

hello1-hello2-hello3-echo hello4

Querido

hello1-hello2-hello3-hello4-hello5-hello6-...
hhh
fuente
La pregunta probablemente debería ser "Cómo utilizar las comillas inversas de Bash de forma recursiva". Eso debería ayudar a los empleados de Google.
Joey Adams
¿Qué es lo que está tratando de hacer? esto no tiene ningún significado.
ghostdog74
1
@joey, título cambiado, bienvenida: D
Stormenet
1
Ups, tacha eso. Debe leer "¿Cómo anido comillas inversas en bash?" . Tengo recursividad y anidación mezclados.
Joey Adams
Las comillas inversas son deprecated, por tanto, útiles $(cmd).
Timo

Respuestas:

145

Utilice en su $(commands)lugar:

$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4

$(commands) hace lo mismo que las comillas invertidas, pero puede anidarlas.

También te pueden interesar las ampliaciones de la gama Bash:

echo hello{1..10}
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10
Joey Adams
fuente
+1 como el {1..10}. ¿Limitarlo con matriz? ZSH puede "$ {$ (fecha) [2,4]}". ¿Por qué no: "echo $ {echo hello1 - $ (echo hello2) [1]}"?
hhh
35

si insiste en usar comillas invertidas, se podría hacer lo siguiente

$ echo "hello1-`echo hello2-\`echo hello3-\\\`echo hello4\\\`\``"

tienes que poner barras invertidas, \\ \\\\ \\\\\\\\por 2x y así sucesivamente, es muy feo, úsalo $(commands)como se sugiere.


fuente
11

Cada vez que desee evaluar un comando, utilice command substitution:

$(command)

Siempre que desee evaluar una expresión aritmética, utilice expression substitution:

$((expr))

Puede anidar estos de esta manera:

Digamos que file1.txt tiene 30 líneas de largo y file2.txt tiene 10 líneas, entonces puedes evaluar una expresión como esta:

$(( $(wc -l file1.txt) - $(wc -l file2.txt) ))

que daría como resultado 20 (la diferencia en el número de líneas entre dos archivos).

toobsco42
fuente
10

Es mucho más fácil si usa la $(cmd) sintaxis de sustitución de comandos de bash , que es mucho más fácil de anidar:

$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4
Mark Rushakoff
fuente
5
Esto no se limita a bash . Está disponible en todos los shells que cumplen con POSIX 1003.1 ("shells POSIX") y la mayoría de los shell derivados de Bourne ( ksh , ash , dash , bash , zsh , etc.) aunque no en el shell Bourne real (es decir, heirloom.sourceforge.net /sh.html ).
Chris Johnsen
¡guau, la marca de tiempo en esta respuesta es IDÉNTICA a la de @joey_adams! Sincronización en su significado más literal :) Votando a favor aquí también (:
drevicko
0

A veces, el anidamiento de comillas invertidas se puede sustituir por xargsy tuberías

$ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1
hello1 hello2 hello3 hello4

Los inconvenientes de esta solución son:

  • Todos los argumentos deben proporcionarse en orden inverso (4 → 1);
  • Todos los argumentos se separan por espacios (se pueden resolver con tr):

    $ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1 | tr ' ' '-'
    hello1-hello2-hello3-hello4


Vamos a mostrar un caso de uso real.

Los siguientes comandos funcionan en bash, pero no en tcsh (la anidación de comillas inversas no se maneja muy bien en tcsh)

$ ls $(dirname $(which bash))
$ ls `dirname \`which bash\``

Pueden sustituirse por

$ which bash | xargs dirname | xargs ls
GC
fuente