651 Stimmen

Erweiterung von Variablen in einfachen Anführungszeichen in einem Bash-Befehl

Ich möchte einen Befehl von einer Bash-Skript die einfache Anführungszeichen und einige andere Befehle innerhalb der einfachen Anführungszeichen und eine Variable enthält.

z.B.. repo forall -c '....$variable'

In diesem Format, $ ist escaped und die Variable wird nicht erweitert.

Ich habe die folgenden Varianten ausprobiert, aber sie wurden abgelehnt:

repo forall -c '...."$variable" '

repo forall -c " '....$variable' "

" repo forall -c '....$variable' "

repo forall -c "'" ....$variable "'"

Wenn ich den Wert anstelle der Variablen einsetze, wird der Befehl ordnungsgemäß ausgeführt.

Bitte sagen Sie mir, was ich falsch mache.

140voto

Mark Reed Punkte 85468

En repo Kommando kann es egal sein, was für Zitate es bekommt. Wenn Sie eine Parametererweiterung benötigen, verwenden Sie doppelte Anführungszeichen. Wenn das bedeutet, dass Sie viel mit Backslash schreiben müssen, verwenden Sie für das meiste einfache Anführungszeichen und dann für den Teil, in dem Sie die Erweiterung benötigen, doppelte Anführungszeichen.

repo forall -c 'literal stuff goes here; '"stuff with $parameters here"' more literal stuff'

Eine Erläuterung folgt, falls Sie daran interessiert sind.

Wenn Sie einen Befehl von der Shell aus ausführen, erhält dieser Befehl als Argumente ein Array von null-terminierten Zeichenketten. Diese Strings können absolut jede Nicht-Null-Zeichen.

Aber wenn die Shell dieses Array von Zeichenketten aus einer Befehlszeile aufbaut, interpretiert sie einige Zeichen speziell; dies soll die Eingabe von Befehlen erleichtern (ja, ermöglichen). Zum Beispiel zeigen Leerzeichen normalerweise die Grenze zwischen Zeichenketten im Array an; aus diesem Grund werden die einzelnen Argumente manchmal "Wörter" genannt. Aber ein Argument kann trotzdem Leerzeichen enthalten; Sie brauchen nur eine Möglichkeit, der Shell mitzuteilen, dass Sie das wollen.

Sie können einen Backslash vor einem beliebigen Zeichen (einschließlich Leerzeichen oder einem anderen Backslash) verwenden, um der Shell mitzuteilen, dass sie dieses Zeichen wörtlich behandeln soll. Aber während Sie etwas wie dies tun können:

reply=\”That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier

...kann es ermüdend werden. Deshalb bietet die Shell eine Alternative: Anführungszeichen. Diese gibt es in zwei Hauptvarianten.

Doppelte Anführungszeichen werden als "gruppierende Anführungszeichen" bezeichnet. Sie verhindern, dass Platzhalter und Aliasnamen erweitert werden, dienen aber hauptsächlich dazu, Leerzeichen in ein Wort einzufügen. Andere Dinge wie Parameter- und Befehlsexpansion (die Art von Dingen, die durch ein $ ) finden immer noch statt. Und wenn Sie ein wörtliches Anführungszeichen in Anführungszeichen setzen wollen, müssen Sie es natürlich mit einem Backslash versehen:

reply="\"That'll be \$4.96, please,\" said the cashier"

Einfache Anführungszeichen sind noch drakonischer. Alles, was dazwischen steht, wird völlig wörtlich genommen, auch Backslashes. Es gibt absolut keine Möglichkeit, ein wörtliches einfaches Anführungszeichen in einfache Anführungszeichen zu setzen.

Glücklicherweise sind die Anführungszeichen in der Shell sind keine Worttrennzeichen ; von selbst beenden sie kein einziges Wort. Sie können innerhalb eines Wortes in Anführungszeichen ein- und aussteigen, auch zwischen verschiedenen Arten von Anführungszeichen, um das gewünschte Ergebnis zu erzielen:

reply='"That'\''ll be $4.96, please," said the cashier'

Das ist einfacher - viel weniger Backslashes, obwohl die Abfolge von close-single-quote, backslashed-literal-single-quote, open-single-quote etwas gewöhnungsbedürftig ist.

Moderne Shells haben einen weiteren Anführungsstil hinzugefügt, der nicht durch den POSIX-Standard spezifiziert ist, in dem das führende einfache Anführungszeichen mit einem Dollarzeichen vorangestellt wird. Strings, die auf diese Weise in Anführungszeichen gesetzt werden, folgen ähnlichen Konventionen wie String-Literale in der ANSI-Standardversion der Programmiersprache C und werden daher manchmal als "ANSI-Strings" bezeichnet und die $' ... ' Paar "ANSI-Anführungszeichen". Innerhalb solcher Zeichenketten gilt der obige Ratschlag, Backslashes wörtlich zu nehmen, nicht mehr. Stattdessen werden sie wieder zu etwas Besonderem - Sie können nicht nur ein einzelnes Anführungszeichen oder einen Backslash einfügen, indem Sie einen Backslash voranstellen, sondern die Shell expandiert auch die ANSI-C-Zeichen-Escapes (wie \n für einen Zeilenumbruch, \t für die Registerkarte, und \xHH für das Zeichen mit hexadezimalem Code HH ). Andernfalls verhalten sie sich jedoch wie Zeichenketten in einfachen Anführungszeichen: Es findet keine Parameter- oder Befehlssubstitution statt:

reply=$'"That\'ll be $4.96, please," said the cashier'

Wichtig ist, dass die einzelne Zeichenfolge, die in der Datei reply Variable ist genau dasselbe in all diesen Beispielen. Nachdem die Shell eine Befehlszeile geparst hat, gibt es für den ausgeführten Befehl keine Möglichkeit, genau festzustellen, wie die einzelnen Argumente tatsächlich eingegeben wurden - oder sogar wenn es wurde eingegeben und nicht irgendwie programmatisch erstellt.

6voto

Manmohan Punkte 178

Im Folgenden wird beschrieben, was bei mir funktioniert hat.

QUOTE="'"
hive -e "alter table TBL_NAME set location $QUOTE$TBL_HDFS_DIR_PATH$QUOTE"

2voto

ecv Punkte 708

EDIT: (Wie in den fraglichen Kommentaren:)

Seitdem habe ich mich damit befasst. Ich hatte das Glück, dass ich Repo herumliegen hatte. Es ist mir immer noch nicht klar, ob man seine Befehle zwangsweise in einfache Anführungszeichen setzen muss. Ich habe mir die Repo-Syntax angesehen und ich glaube nicht, dass man das muss. Man kann doppelte Anführungszeichen um den Befehl herum verwenden und dann innerhalb der Anführungszeichen die gewünschten einfachen und doppelten Anführungszeichen verwenden, sofern man die doppelten Anführungszeichen ausschließt.

2voto

AndrewD Punkte 4319

einfach printf verwenden

anstelle von

repo forall -c '....$variable'

printf verwenden, um das Variablen-Token durch die erweiterte Variable zu ersetzen.

Zum Beispiel:

template='.... %s'

repo forall -c $(printf "${template}" "${variable}")

0voto

user3734617 Punkte 81

Variablen können einfache Anführungszeichen enthalten.

myvar=\'....$variable\'

repo forall -c $myvar

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X