Comment emboîter correctement les backticks Bash

92

Soit j'ai manqué un jeu, soit un contrecoup ne semble pas fonctionner avec trop de boucle de devis de programmeur.

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

hello1-hello2-hello3-echo hello4

Voulait

hello1-hello2-hello3-hello4-hello5-hello6-...
hhh
la source
La question devrait probablement lire "Comment utiliser les backticks Bash de manière récursive". Cela devrait aider les Googleurs.
Joey Adams
qu'est-ce que vous essayez de faire.? cela n'a aucun sens.
ghostdog74
1
@joey, titre changé, bienvenue: D
Stormenet
1
Oups, grattez ça. Il devrait lire "Comment imbriquer des backticks dans bash?" . J'ai confondu la récursion et l'imbrication.
Joey Adams
Les backticks sont deprecateddonc utilisés $(cmd).
Timo

Réponses:

145

Utilisez à la $(commands)place:

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

$(commands) fait la même chose que les backticks, mais vous pouvez les imbriquer.

Les extensions de la gamme Bash peuvent également vous intéresser:

echo hello{1..10}
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10
Joey Adams
la source
+1 comme le {1..10}. Le limiter avec un tableau? ZSH peut "$ {$ (date) [2,4]}". Pourquoi pas: "echo $ {echo hello1 - $ (echo hello2) [1]}"?
hhh
35

si vous insistez pour utiliser des backticks, le suivi pourrait être fait

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

vous devez mettre des contre-obliques, \\ \\\\ \\\\\\\\par 2x et ainsi de suite, c'est juste très moche, utilisez $(commands)comme autre suggéré.

TU
la source
11

Chaque fois que vous souhaitez évaluer une commande, utilisez command substitution:

$(command)

Chaque fois que vous souhaitez évaluer une expression arithmétique, utilisez expression substitution:

$((expr))

Vous pouvez les imbriquer comme ceci:

Supposons que file1.txt comporte 30 lignes et file2.txt 10 lignes, que vous pouvez évaluer une expression comme celle-ci:

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

qui produirait 20 (la différence de nombre de lignes entre deux fichiers).

toobsco42
la source
10

C'est beaucoup plus facile si vous utilisez la $(cmd) syntaxe de substitution de commande de bash , qui est beaucoup plus facile à imbriquer:

$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4
Mark Rushakoff
la source
5
Cela ne se limite pas à bash . Il est disponible dans tous les shells conformes à POSIX 1003.1 («shells POSIX») et dans la plupart des shell dérivés de Bourne ( ksh , ash , dash , bash , zsh , etc.) mais pas dans le véritable Bourne shell (ie heirloom.sourceforge.net /sh.html ).
Chris Johnsen
wow, l'horodatage de cette réponse est IDENTIQUE à celui de la réponse @joey_adams! Synchronisity dans son sens le plus littéral :) Voter ici aussi (:
drevicko
0

Parfois, l'imbrication de backtick peut être remplacée par xargset des tuyaux

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

Les inconvénients de cette solution sont:

  • Tous les arguments doivent être fournis dans l'ordre inverse (4 → 1);
  • Tous les arguments deviennent séparés par un espace (résoluble avec tr):

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


Montrons un vrai cas d'utilisation.

Les commandes suivantes fonctionnent dans bash, mais pas dans tcsh (l'imbrication de backtick n'est pas très bien gérée dans tcsh)

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

Ils peuvent être remplacés par

$ which bash | xargs dirname | xargs ls
GC
la source