Come annidare correttamente i backtick di Bash


92

O mi sono perso qualche contraccolpo o il contraccolpo non sembra funzionare con troppi cicli di citazione del programmatore.

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

hello1-hello2-hello3-echo hello4

Ricercato

hello1-hello2-hello3-hello4-hello5-hello6-...

La domanda dovrebbe probabilmente essere "Come usare i backtick di Bash in modo ricorsivo". Questo dovrebbe aiutare i googler là fuori.
Joey Adams

che cosa stai cercando di fare? questo non ha alcun significato.
ghostdog74

1
@joey, titolo cambiato, sicuro benvenuto: D
Stormenet

1
Ops, cancellalo. Dovrebbe essere visualizzato "Come annido i backtick in bash?" . Ho confuso ricorsione e annidamento.
Joey Adams

deprecatedQuindi utilizzare i backtick $(cmd).
Timo

Risposte:


145

Usa $(commands)invece:

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

$(commands) fa la stessa cosa dei backtick, ma puoi annidarli.

Potresti anche essere interessato alle espansioni della gamma Bash:

echo hello{1..10}
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10

+1 come {1..10}. Limitare con l'array? ZSH può "$ {$ (date) [2,4]}". Perché no: "echo $ {echo ciao1 - $ (echo ciao2) [1]}"?
hhh

35

se insisti a usare i backtick, puoi fare quanto segue

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

devi mettere i backslash, \\ \\\\ \\\\\\\\di 2x e così via, è solo molto brutto, usa $(commands)come altri suggeriti.


11

Ogni volta che vuoi valutare un comando usa command substitution:

$(command)

Ogni volta che vuoi valutare un'espressione aritmetica usa expression substitution:

$((expr))

Puoi annidarli in questo modo:

Diciamo che file1.txt è lungo 30 righe e file2.txt è lungo 10 righe, quindi puoi valutare un'espressione come questa:

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

che produrrebbe 20 (la differenza nel numero di righe tra due file).


10

È molto più semplice se usi la $(cmd) sintassi di sostituzione dei comandi di bash , che è molto più facile da annidare:

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

5
Questo non è limitato a bash . È disponibile in tutte le shell conformi a POSIX 1003.1 ("shell POSIX") e nella maggior parte delle shell derivate da Bourne ( ksh , ash , dash , bash , zsh , ecc.) Sebbene non la shell Bourne reale (cioè heirloom.sourceforge.net /sh.html ).
Chris Johnsen

wow, il timestamp su questa risposta è IDENTICO a quello sulla risposta @joey_adams! Sincronismo nel suo significato più letterale :) Upvoting anche qui (:
drevicko

0

A volte l'annidamento di backtick può essere sostituito con xargse pipe

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

Gli svantaggi di questa soluzione sono:

  • Tutti gli argomenti devono essere forniti in ordine inverso (4 → 1);
  • Tutti gli argomenti diventano separati da spazi (risolvibili con tr):

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


Mostriamo un caso d'uso reale.

I seguenti comandi funzionano in bash, ma non in tcsh (l'annidamento del backtick non è gestito molto bene in tcsh)

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

Possono essere sostituiti con

$ which bash | xargs dirname | xargs ls
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.