Qual è la differenza tra $ (stuff) e `stuff`?


265

Esistono due sintassi per la sostituzione dei comandi: con parentesi in dollari e con backtick. In esecuzione top -p $(pidof init)e top -p `pidof init`dà lo stesso output. Sono due modi di fare la stessa cosa o ci sono differenze?


18

43
Per un secondo ho pensato che fosse una domanda jQuery.
David Murdoch,

Il risultato potrebbe dipendere dalla shell - alcuni supportano entrambi.
artdanil,

Risposte:


360

I backquotes vecchio stile ` `trattano le barre rovesciate e la nidificazione un po 'diversa. Il nuovo stile $()interpreta tutto nel mezzo ( )come un comando.

echo $(uname | $(echo cat))
Linux

echo `uname | `echo cat``
bash: command substitution: line 2: syntax error: unexpected end of file
echo cat

funziona se i backquotes nidificati sono sottoposti a escape:

echo `uname | \`echo cat\``
Linux

backslash fun:

echo $(echo '\\')
\\

echo `echo '\\'`
\

Il nuovo stile si $()applica a tutte le shell conformi a POSIX .
Come mouviciel ha sottolineato, il vecchio stile ` `potrebbe essere necessario per le conchiglie più vecchie.

A parte il punto di vista tecnico, il vecchio stile ` `ha anche uno svantaggio visivo:

  • Difficile da notare: I like $(program) better than `program`
  • Facilmente confuso con una sola citazione: '`'`''`''`'`''`'
  • Non è così facile da scrivere (forse nemmeno sul layout standard della tastiera)

(e SE usa ` `per il proprio scopo, è stato un dolore scrivere questa risposta :)


10
L'unica cosa che aggiungerei è che chiamo '(' un paren, non una parentesi (che è '[').
Kendall Helmstetter Gelner

@Kendall: e qui ho pensato che "{" fosse la parentesi sinistra per tutti quegli anni ...
SamB

5
@Sam: di { }solito viene chiamato "parentesi graffe" o "parentesi graffe" en.wikipedia.org/wiki/Braces_(punctuation)#Braces
Jørn Schou-Rode

2
Mi riferisco anche a "{" come parentesi graffe. Anche se sembra strano, è necessario aggiungere il qualificatore "ricci" se si chiamano le altre parentesi ... Immagino sia solo perché si arricciano.
Kendall Helmstetter Gelner,

1
@slim Non lo so sulle tastiere degli Stati Uniti / Regno Unito, ma sulle tastiere spagnole `è un tasto morto, quindi devo digitare un doppio backtick (qualcosa che di solito dimentico che posso persino fare) o backtick quindi lo spazio, che è un dolore.
Darkhogg

41

La differenza evidente che osservo è che non puoi nidificare i backtick mentre puoi nidificare $(). Forse entrambi esistono per motivi legati al passato. Allo stesso modo, i comandi .e sourcesono sinonimi.


10
Alcune shell derivate da Bourne non riconoscono source. Dash è un esempio.
Dennis Williamson,

14
Non è vero. Puoi annidare il backtick a qualsiasi livello, solo più dolorosamente. Si noti che entrambi $(...)e `...`sono standard (quest'ultimo è deprecato) mentre .è standard ma nonsource
Stéphane Chazelas,

3
Correzione, solo in (t)cshnon possono essere nidificati. (t)cshnon supportare $(...)però. Tuttavia supportano source(e non .).
Stéphane Chazelas,

28

$()non funziona con la vecchia shell Bourne. Ma è stato anni decenni da quando ho lavorato con il vecchio Bourne shell.


Vecchi come negli anni '70 e nei primi anni '80, giusto?
Christopher

6

Un'altra nota, $()utilizzerà più risorse di sistema rispetto all'uso dei backtick, ma è leggermente più veloce.

Nel mastering dello scripting della shell Unix , Randal K. Michael aveva fatto un test in un capitolo chiamato "24 modi per elaborare un file riga per riga".


2
Questa affermazione non ha senso. Non vi è alcun motivo per cui dovrebbe essere più veloce in quanto utilizza semplicemente una notazione diversa per il parser.
schily,

@schily: Forse, cito solo dal libro, puoi leggerlo per maggiori dettagli.
cuonglm,

3
Tenderei ad essere d'accordo con @schily ... perché dovrebbero essere necessarie più risorse?
Wildcard

2
@Wildcard, suppongo sia perché $()rende il tuo script un byte più grande di se usato `(supponendo che non li annidi e non usi le barre rovesciate). Quanto a ciò sarebbe più veloce da analizzare, ciò varierebbe tra shell e sarebbe irrilevante in quanto trascurabile rispetto al costo di creazione di una pipe e di un fork di processo che comporta la sostituzione del comando.
Stéphane Chazelas,

5

Per aggiungere ciò che altri hanno detto qui, è possibile utilizzare i backtick per simulare commenti incorporati:

echo foo `# I'm a comment!` bar

L'uscita è: foo bar.

Vedere di seguito per ulteriori informazioni: https://stackoverflow.com/a/12797512 (notare anche i commenti sotto quel post.)


1

La $()sintassi non funzionerà con la vecchia shell Bourne.
Con le nuove shell ` `e $()sono equivalenti, ma $()è molto più comodo da usare quando è necessario nidificare più comandi.

Per esempio :

echo $(basename $(dirname $(dirname /var/adm/sw/save )))

è più facile da digitare ed eseguire il debug di:

echo `basename \`dirname \\\`dirname /var/adm/sw/save \\\`\``

1
Mentre $ () può sembrare carino, è un problema quando si implementa un parser correlato perché richiede un parser doppio ricorsivo.
schily,

6
@schily Dall'altro lato, quale sarebbe una shell senza un buon parser.
Emmanuel,

1
Il problema è che è necessario sapere dove finisce la stringa prima di chiamare il parser. Questo è relativamente semplice con i backtick, ma è difficile con le parentesi poiché sono usati per vari scopi nella shell. Quindi hai bisogno del parser due volte e in un modo che non esiste nella Bourne Shell.
schily,
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.