2011-01-16 7 views
178

In sh/ksh/bash die Ausgabe eines Befehls zu speichern als eine Variable, die Sie entweder

MY_VAR=$(command) 
#or you can do 
MY_VAR=`command` 

Was ist der Unterschied, wenn ein zwischen den beiden Methoden ist zu tun?

+21

Siehe [BashFAQ/082] (http://mywiki.wooledge.org/BashFAQ/082). –

+0

Das verschachtelte Problem finden Sie in der Git Coding Guideline: siehe [meine Antwort unten] (http://stackoverflow.com/a/24592916/6309). – VonC

Antwort

199

Die Backticks/Grabmarks wurden zugunsten von $() für Befehlssubstitution als veraltet eingestuft, da $() problemlos in sich selbst verschachtelt werden kann, wie in $(echo foo$(echo bar)). Es gibt andere Unterschiede, wie zum Beispiel, wie umgekehrte Schrägstriche in der backtick/graemark-Version geparst werden.

Siehe BashFAQ/082 aus verschiedenen Gründen, um immer die $ (...) Syntax zu bevorzugen.

Weitere Informationen zu den verschiedenen Unterschieden finden Sie in der Spezifikation POSIX.

+20

Guter Link, aber dieser Text wird nicht durch _deprecate_ backquotes zugunsten von '$ (...)' ersetzt - er merkt sie nur als Alternativen an. –

+19

@NormanGray POSIX darf nicht das Wort * veraltet * sagen, aber es sagt '" die Backquoted Vielfalt der Befehlsersetzung wird nicht empfohlen "' das ist nur eine langatmige Art zu sagen, veraltet IMHO – SiegeX

+7

POSIX verwarf nicht Backticks, sondern fügte hinzu '$ (...)' als alternative Methode. Es gibt keinen bekannten Implementierungsfehler mit Backticks, aber es gibt viele bekannte Implementierungsfehler mit '$ (...)'. Aus Gründen der Portabilität wird empfohlen, Backticks für nicht verschachtelte Aufrufe zu verwenden. '$ (...)' benötigt einen rekursiven Parser, aber dies wurde nicht mit ksh86 verwendet, das das Feature eingeführt hat. Eine Liste korrekter Implementierungen finden Sie unter http://www.in-ulm.de/~masheck/variant/cmd-subst/. Eine konforme Shell muss alle Fälle außer Fall D.2 unterstützen. – schily

5

Es gibt wenig Unterschied, außer für welche nicht deklarierten Zeichen Sie innerhalb des Befehls verwenden können. Sie können sogar `...` Befehle in $ (...) Einsen (und umgekehrt) für eine kompliziertere zwei Ebenen tiefe Befehlsersetzung setzen.

Es gibt eine etwas andere Interpretation des Backslash-Zeichens/-Operators. Unter anderem beim Schachteln `...` Substitution Befehle, müssen Sie die inneren ` Escape-Zeichen mit \, während bei $() Substitutions es die Verschachtelung automatisch versteht.

22

Wenn das ältere Back-Tick-Formular verwendet wird, behält der Backslash seine wörtliche Bedeutung bei, außer wenn $, `, oder \ folgen. Der erste Back-Tick, dem kein Backslash vorangestellt ist, beendet die Befehlsersetzung.

Bei Verwendung des neueren Formulars $(command) bilden alle Zeichen zwischen den Klammern den Befehl; keine werden speziell behandelt.

Beide Formulare können verschachtelt werden, aber die Back-Tick-Variante erfordert das folgende Formular.

`echo \`foo\`` 

Im Gegensatz zu:

$(echo $(foo)) 
+1

Geringfügige Korrektur, sowohl die Backtick Version als auch die '$()' Version sind POSIX kompatibel. – SiegeX

+0

Bekannt und aktualisiert, danke. – ocodo

32

verhalten sie sich gleich. Der Unterschied ist, syntaktischer: es ist einfacher zu nisten $() als ``:

listing=$(ls -l $(cat filenames.txt)) 

gegen

listing=`ls -l \`cat filenames.txt\`` 
+7

'echo $ (echo \ $ abc)' ist nicht das gleiche wie 'echo echo \ $ abc''' - Unterschiede gibt es auch für' '(echo \' '' '' '' ' \ "' –

22

Juli 2014: Die commit f25f5e6 (von Elia Pinto (devzero2000) April 2014, Git 2.0) ergänzt die Verschachtelung Ausgabe:

Das Backquoted-Formular ist die traditionelle Methode für die Befehlsersetzung und wird von POSIX unterstützt.
Allerdings werden alle außer den einfachsten Anwendungen schnell kompliziert.
Insbesondere Embedded Command Substitutions und/oder die Verwendung von Anführungszeichen erfordern vorsichtiges Escaping mit dem Backslash-Zeichen
.

Deshalb ist die git/Documentation/CodingGuidelines erwähnt:

Wir bevorzugen $(...) für Kommandosubstitution; im Gegensatz zu `` Nestern.
Es sollte die Art und Weise gewesen sein, wie Bourne es vom ersten Tag an buchstabierte, aber leider nicht.

thitoncommented:

Deshalb `echo `foo`` wird nicht wegen der inhärenten Mehrdeutigkeit im Allgemeinen arbeiten, weil jeder `` Öffnen oder Schließen werden kann.
Es kann für Sonderfälle wegen Glück oder Besonderheiten funktionieren.


Update Januar 2016: Git 2.8 (März 2016) wird vollständig aus Backticks befreien.

Siehe commit ec1b763, commit 9c10377, commit c7b793a, commit 80a6b3f, commit 9375dcf, commit e74ef60, commit 27fe43e, commit 2525c51, commit becd67f, commit a5c98ac, commit 8c311f9, commit 57da049, commit 1d9e86f, commit 78ba28d, commit efa639f, commit 1be2fa0, commit 38e9476, commit 8823d2f, commit 32858a0, commit cd914d8 (12. Januar 2016) durch Elia Pinto (devzero2000).
(Verschmelzung durch Junio C Hamano -- gitster -- in commit e572fef 22 Jan 2016)

Von Git 2.8 ab, es ist alles $(...), nicht mehr `...`.

+1

@VonC Hinweis an mich selbst: Das ist mein 150. Nekromanten-Abzeichen. – VonC

+0

'$()' ist auch POSIX-spezifiziert - ein Zitat, das Backticks als "POSIX-unterstützt" beschreibt, um so anzudeuten, dass dies für sie einzigartig ist, ist irreführend. Es ist nur (vor 1970) Pre-POSIX Bourne, wo Backticks die einzige unterstützte Syntax sind. –