Was ist der Unterschied zwischen $ (stuff) und `stuff`?

265

Es gibt zwei Syntaxen für die Befehlssubstitution: mit Dollar-Klammern und mit Backticks. Laufen top -p $(pidof init)und top -p `pidof init`gibt die gleiche Ausgabe. Gibt es zwei Möglichkeiten, dasselbe zu tun, oder gibt es Unterschiede?

Tshepang
quelle
18
Siehe auch: BashFAQ / 082 .
Dennis Williamson
42
Für eine Sekunde dachte ich, dies sei eine jQuery-Frage.
David Murdoch
Das Ergebnis kann von der Shell abhängen - einige unterstützen beides.
Artdanil

Antworten:

359

Die Backquotes im alten Stil ` `behandeln Backslashes und Nesting etwas anders. Der neue Stil $()interpretiert alles dazwischen ( )als Befehl.

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

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

funktioniert, wenn die geschachtelten Anführungszeichen maskiert sind:

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

Backslash-Spaß:

echo $(echo '\\')
\\

echo `echo '\\'`
\

Der neue Stil $()gilt für alle POSIX- konformen Shells.
Wie Mouviciel betonte, ` `könnte für ältere Muscheln ein alter Stil erforderlich sein.

Abgesehen von der technischen Sicht hat der alte Stil ` `auch einen optischen Nachteil:

  • Schwer zu merken: I like $(program) better than `program`
  • Mit einem einfachen Anführungszeichen leicht zu verwechseln: '`'`''`''`'`''`'
  • Nicht so einfach zu tippen (vielleicht nicht einmal im Standardlayout der Tastatur)

(und SE verwendet ` `für eigene Zwecke, es war ein Schmerz, diese Antwort zu schreiben :)

wedeln
quelle
10
Das einzige, was ich hinzufügen möchte, ist, dass ich '(' eine Klammer, keine Klammer (die '[' ist).
Kendall Helmstetter Gelner
@Kendall: und hier dachte ich '{' war die linke Klammer für all die Jahre ...
SamB
5
@ Sam: { }wird normalerweise "geschweifte Klammern" oder "geschweifte Klammern" genannt de.wikipedia.org/wiki/Braces_(punctuation)#Braces
Jørn Schou-Rode
2
Ich bezeichne '{' auch als geschweifte Klammern. Obwohl es seltsam erscheint, müssen Sie das Qualifikationsmerkmal "lockig" hinzufügen, wenn Sie die anderen Dinge als Klammern bezeichnen.
Kendall Helmstetter Gelner
1
@slim Ich weiß es nicht auf US / UK-Tastaturen, aber auf spanischen Tastaturen `ist eine tote Taste, also muss ich entweder ein Double-Backtick (etwas, das ich normalerweise vergesse, kann ich sogar tun) oder ein Backtick und dann ein Leerzeichen eingeben Schmerzen.
Darkhogg
41

Der offensichtliche Unterschied, den ich beobachte, ist, dass Sie Backticks nicht verschachteln können, während Sie verschachteln können $(). Vielleicht existieren beide aus alten Gründen. Ebenso sind die Befehle .und sourceSynonyme.

balki
quelle
10
Einige von Borowski abgeleitete Shells erkennen sie nicht source. Dash ist ein Beispiel.
Dennis Williamson
14
Das ist nicht wahr. Sie können Backtick zu jedem Level verschachteln, nur schmerzhafter. Beachten Sie, dass beide $(...)und `...`Standard sind (letzteres ist veraltet), während .es Standard ist, aber nichtsource
Stéphane Chazelas
3
Korrektur, nur in (t)cshkönnen sie nicht verschachtelt werden. (t)cshaber nicht unterstützen $(...). Sie unterstützen source(und nicht .) obwohl.
Stéphane Chazelas
28

$()funktioniert nicht mit alter Bourne-Shell. Aber es ist Jahre Jahrzehnte her, seit ich mit der alten Bourne-Shell gearbeitet habe.

mouviciel
quelle
Alt wie in den 1970ern und frühen 1980ern, richtig?
Christopher
6

Ein weiterer Hinweis, $()wird mehr Systemressourcen als die Verwendung von Backticks verwenden, ist aber etwas schneller.

Randal K. Michael hatte in Mastering Unix Shell Scripting einen Test in einem Kapitel mit dem Titel "24 Möglichkeiten, eine Datei Zeile für Zeile zu verarbeiten" durchgeführt.

cuonglm
quelle
2
Diese Behauptung ist Unsinn. Es gibt keinen Grund, warum es schneller sein sollte, da es nur eine andere Notation für den Parser verwendet.
Schily
@schily: Vielleicht zitiere ich nur aus dem Buch, du kannst es für mehr Details lesen.
Dienstag,
3
Ich würde eher mit @schily übereinstimmen ... warum würde es mehr Ressourcen erfordern?
Wildcard
2
@Wildcard, ich nehme an, das liegt daran, $()dass Ihr Skript ein Byte größer ist als bei Verwendung `(vorausgesetzt, Sie verschachteln sie nicht und verwenden keine Backslashes). Was schneller zu analysieren wäre, würde zwischen den Schalen variieren und wäre irrelevant und vernachlässigbar im Vergleich zu den Kosten für die Erstellung eines Rohrs und das Verzweigen von Prozessen, die eine Befehlssubstitution mit sich bringt.
Stéphane Chazelas
5

Um das, was andere hier gesagt haben, zu ergänzen, können Sie die Backticks verwenden, um Inline-Kommentare zu simulieren:

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

Die Ausgabe lautet: foo bar.

Weitere Informationen finden Sie im Folgenden: https://stackoverflow.com/a/12797512 (Beachten Sie auch die Kommentare unter diesem Beitrag.)

phk
quelle
1

Die $()Syntax funktioniert nicht mit der alten Borowski-Shell.
Mit neueren Shells ` `und $()Äquivalenten $()ist die Verwendung jedoch wesentlich bequemer, wenn Sie mehrere Befehle verschachteln müssen.

Zum Beispiel :

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

ist einfacher zu tippen und zu debuggen als:

echo `basename \`dirname \\\`dirname /var/adm/sw/save \\\`\``
Emmanuel
quelle
1
$ () Sieht zwar gut aus, ist jedoch ein Problem beim Implementieren eines verwandten Parsers, da ein doppelter rekursiver Parser erforderlich ist.
Schily
6
@schily Auf der anderen Seite, was wäre eine Shell ohne einen guten Parser.
Emmanuel
1
Das Problem ist, dass Sie wissen müssen, wo die Zeichenfolge endet, bevor Sie den Parser aufrufen. Dies ist bei den Backticks relativ einfach, bei den Brackets jedoch schwierig, da sie in der Shell für verschiedene Zwecke verwendet werden. Sie benötigen den Parser also zweimal und auf eine Weise, die es in der Bourne-Shell nicht gibt.
Schily