Wie kann ich eine Bash-Variable exakt als Befehl ausführen, ohne zusätzliche Anführungszeichen?

Wie kann ich eine Bash-Variable exakt als Befehl ausführen, ohne zusätzliche Anführungszeichen?

Ich versuche, ein Skript zu erstellen, das einen auszuführenden Befehl als Zeichenfolge speichern muss. Die betreffende Zeichenfolge muss Anführungszeichen enthalten, und beim Versuch, sie auszuführen, fügt Bash zusätzliche Anführungszeichen hinzu, was in einigen Fällen dazu führt, dass der Befehl nicht wie erwartet ausgeführt wird.

Hier ist ein Beispielskript. Der examplein diesem Beispielskript ausgeführte Befehl tut offensichtlich nichts und gibt lediglich aus command not found, Sie können das Skript jedoch trotzdem ausführen und sehen, wovon ich spreche, da ich -xdie #!/bin/bashZeile so ergänzt habe, dass der genaue ausgeführte Befehl ausgedruckt wird.

Beispiel:

#!/bin/bash -x

#command typed explicitly
example -options "-i filename"

#command stored in string first
commandstring='example -options "-i filename"'
echo "running command: ${commandstring}"
${commandstring}

Die Ausgabe beim Ausführen dieses Skripts ist für mich (unter Ignorierung der beiden „Befehl nicht gefunden“-Fehler):

+ example -options '-i filename'
+ commandstring='example -options "-i filename"'
+ echo 'running command: example -options "-i filename"'
running command: example -options "-i filename"
+ example -options '"-i' 'filename"'

Sie können also sehen, dass die erste Zeile natürlich wie erwartet ausgeführt wird, wenn der Befehlszeilenparameter angegeben wird:

-i filename

Obwohl der echoBefehl die Zeichenfolge auf eine Weise druckt, die auch perfekt ausgeführt werden würde, ändert sich die Zeichenfolge, wenn sie in die Befehlszeile eingefügt wird, und der übergebene Parameter wird

'"-i' 'Dateiname"'

das zusätzliche Anführungszeichen enthält, und dies führt dazu, dass der eigentliche Befehl, den ich in meinem echten Skript verwende, fehlschlägt.

Gibt es eine Möglichkeit, dies zu verhindern?

Antwort1

Wenn Sie verwenden bash, ist es am einfachsten, einen Befehl exakt zu speichern, indem Sie ihn in ein Array einfügen. Wenn der Befehl, den Sie ausführen möchten, lautet:

example -options "-i filename"

Sie können es in einer Array-Variable speichern mit:

commandline=(example -options "-i filename")

Anschließend können Sie den gespeicherten Befehl genauso ausführen, indem Sie das Array in Anführungszeichen mit @ erweitern:

"${commandline[@]}"

Das Wichtigste, was Sie hier wissen müssen, ist, dass die Shell Anführungszeichen ( "'\) anders behandelt, wenn sie direkt in die Befehlszeile eingegeben werden, als wenn sie sie in einer Variablenerweiterung wie in Ihrer findet ${commandstring}. In der Befehlszeile haben Anführungszeichen eine spezielle Anführungszeichenfunktion. In einer Parametererweiterung sind sie ganz normale, nicht spezielle Zeichen. Daher "-i filename"ist ein einzelnes Wort, wenn es in die Befehlszeile eingegeben wird, das als analysiert wird -i filename, aber dieselben Zeichen in einer Variablen werden zu den Wörtern "-iund erweitert filename".


BashFAQ 50behandelt dieses Thema viel ausführlicher.

verwandte Informationen