Die dritte Form ist überhaupt nicht wie die anderen beiden - aber um zu verstehen, warum, müssen wir in die Reihenfolge der Operationen gehen, wenn bash einen Befehl interpretiert, und schauen, welche davon bei jeder Methode befolgt wird verwenden.
eval "$string"
eval "$string"
folgt allen obigen Schritten ab # 1. Also:
>()
werden verarbeitet $foo
werden berücksichtigt sh -c "$string"
... führt das gleiche aus wie eval
, aber in einer neuen Shell, die als separater Prozess gestartet wird ; Änderungen am Variablenstatus, am aktuellen Verzeichnis usw. verfallen daher, wenn dieser neue Prozess beendet wird. (Beachten Sie auch, dass diese neue Shell möglicherweise ein anderer Interpreter ist, der eine andere Sprache unterstützt; dh sh -c "foo"
unterstützt nicht die gleiche Syntax wie bash
, ksh
, zsh
usw.).
$string
... beginnt mit Schritt 5, "Wortteilung".
Was bedeutet das?
printf '%s\n' "two words"
wird also als printf
%s\n
"two
words"
analysiert, im Gegensatz zum üblichen / erwarteten Verhalten von printf
%s\n
two words
(wobei die Anführungszeichen von der Shell verbraucht werden) ).
;
s, &
s oder ähnlich) findet nicht statt. Also:
%Vor%... gibt die folgende Ausgabe aus:
%Vor%... anstelle der folgenden, die sonst erwartet würden:
%Vor% Keine $(foo)
, keine $foo
, keine <(foo)
, etc.
>foo
oder 2>&1
ist nur ein anderes Wort, das durch String-Splitting und nicht durch eine Shell-Direktive erzeugt wird.
Diese Version startet einen neuen Bash-Interpreter, führt den Befehl aus und wird dann beendet, wobei die Steuerung an die ursprüngliche Shell zurückgegeben wird. Sie müssen überhaupt nicht zuerst bash ausführen, Sie können beispielsweise einen Bash-Interpreter von tcsh starten. Sie können dies auch über ein Bash-Skript tun, um mit einer neuen Umgebung zu beginnen oder um die aktuelle Umgebung nicht zu belasten.
BEARBEITEN:
Wie @CharlesDuffy darauf hinweist, dass das Starten einer neuen Bash-Shell auf diese Weise die Shell-Variablen löscht, aber Umgebungsvariablen von dem erzeugten Shell-Prozess geerbt werden.
Wenn eval
verwendet wird, parst die Shell den Befehl zweimal. In dem Beispiel, das Sie angegeben haben, ist $ COMMAND direkt auszuführen oder ein eval
ist äquivalent, aber werfen Sie einen Blick auf die Antwort hier um eine genauere Vorstellung davon zu bekommen, für was eval
gut (oder schlecht) ist.
Es gibt zumindest Zeiten, wenn sie anders sind. Berücksichtigen Sie Folgendes:
%Vor% zeigt die verschiedenen Punkte, an denen die variable Erweiterung durchgeführt wird. Es ist noch deutlicher, wenn wir set -x
first
Wir können hier viel von dem sehen, worüber Charles Duffy in seiner ausgezeichneten Antwort spricht. Wenn Sie zum Beispiel versuchen, die Variable auszuführen, wird $var
direkt ausgegeben, weil die Parametererweiterung und diese früheren Schritte bereits durchgeführt wurden. Daher erhalten wir nicht den Wert von var
, wie wir es mit eval
tun.
Die Option bash -c
erbt nur export
ed -Variablen von der übergeordneten Shell, und da ich var
nicht exportiert habe, ist sie für die neue Shell nicht verfügbar.
Wenn Sie nur den Pfad zur Datei (und nicht eine Instanz von %code% ) benötigen, wird Folgendes gemacht:
%Vor%Versuchen Sie, den Pfad zu den Bildern mit schnellem Code zu ermitteln. Ich habe das, was meiner Meinung nach in Ziel C funktioniert.
%Vor%Um den Pfad für mein .png Bild zu erhalten, habe ich in assets.xcassets gespeichert. Aber ich muss das jetzt in SWIFT tun, nicht in objektiven C.
Ich brauche den Pfad, weil ich versuche, das Bild, das ich dort eingefügt habe, auf ein %code% in iCloud hochzuladen.