Verwendung von Variablen in einfachen Anführungszeichen

11

Ich habe eine Anwendung, die als Eingabeattribute doppelte Anführungszeichen verwendet, die in einfache Anführungszeichen eingebettet sind. Nehmen Sie zum Beispiel diesen richtigen Befehl:

command -p 'cluster="cl1"'

Um dies zu automatisieren, habe ich eine Bash-Datei $CLUSTERals Variable erstellt. Wie soll mein Befehl sein? Mit anderen Worten, was soll ich anstelle von cl1 setzen?

Bitte beachten Sie, dass wenn ich den obigen Befehl geändert habe, er nicht akzeptiert wird. Zum Beispiel: command -p "cluster=cl1"wird nicht akzeptiert

Mohamad-Jaafar NEHME
quelle
2
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
Mikeserv
Eine andere Möglichkeit (wenn Sie es vorziehen, cliohne Anführungszeichen in der CLUSTERVariablen zu speichern ):CLUSTER='cl1'; command -p 'cluster="'"$CLUSTER"'"'
jimmij
Endlich habe ich die richtige Antwort gefunden. Danke @jimmij.
Mohamad-Jaafar NEHME

Antworten:

8

Es sieht so aus, als würde Ihr Befehl möglicherweise Umgebungsvariablen basierend auf Argumenten festlegen, die in der Befehlszeile angegeben wurden. Möglicherweise können Sie Folgendes tun:

CLUSTER=cl1; cluster=$CLUSTER command

... und legen Sie beim Aufruf die Umgebung dafür fest.

Andernfalls begrenzen Shell-Anführungszeichen normalerweise Argumente oder entziehen andere Shell-Sonderzeichen der Shell-Interpretation. Sie können verschiedene Arten von Shell-Anführungszeichen in anderen Arten enthalten (und daher entkommen), basierend auf verschiedenen Regeln:

  • "''''" - Eine Zeichenfolge in weichen Anführungszeichen kann eine beliebige Anzahl von Anführungszeichen enthalten.
  • "\""- Ein \Backslash kann einem "weichen Anführungszeichen innerhalb einer "Zeichenfolge mit weichen Anführungszeichen entgehen .
    • In diesem Zusammenhang \\entgeht auch ein Backslash, das \$Erweiterungstoken und \nEwlines, wie unten angegeben, wird aber ansonsten wörtlich behandelt.
  • "${expand} and then some"- Eine Zeichenfolge in weichen Anführungszeichen kann eine interpretierte Shell- $Erweiterung enthalten.
  • '"\'- Eine 'Zeichenfolge in harten Anführungszeichen kann ein anderes Zeichen als ein Zeichen in 'harten Anführungszeichen enthalten.
  • \- Ein nicht \nzitierter Backslash entgeht jedem folgenden Zeichen für die wörtliche Interpretation - sogar einem weiteren Backslash - mit Ausnahme einer Ewline.
    • In einem \\nEwline-Fall werden sowohl der \Backslash als auch der \nEwline vollständig aus dem resultierenden interpretierten Befehl entfernt.
  • ${parameter+expand "$parameter"}- Anführungszeichen, die sich aus einer Shell-Erweiterung ergeben, dienen mit Ausnahme einiger Sonderfälle fast nie als Trennzeichen. Ich werde es nicht wagen, diese hier weiter zu beschreiben.

Ich finde es seltsam, dass jede Anwendung Anführungszeichen in ihren Befehlszeilenargumenten interpretiert. Eine solche Praxis macht insofern wenig Sinn, als - zumindest für Muscheln - der Hauptzweck eines Zitats im Allgemeinen darin besteht, ein Argument abzugrenzen. Bei Aufruf werden immer jedoch Argumente bereits begrenzt mit \0NULZeichen und so ein Angebot kann nicht viel Zweck dienen.

Selbst eine Shell wird sich normalerweise nur dann die Mühe machen, Anführungszeichen in einem ihrer Aufrufargumente zu interpretieren, wenn sie mit einem -cSchalter aufgerufen wird. Dies bedeutet, dass ihr erster Operand tatsächlich ein Shell-Skript ist, das beim Aufruf ausgeführt werden soll. Dies ist ein Fall von zweimal ausgewerteten Eingaben.

Trotzdem können Sie eine Reihe von Maßnahmen ergreifen, um wörtliche Anführungszeichen über Argumente in der Befehlszeile zu übergeben. Beispielsweise:

CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"

Wie ich bereits in einem Kommentar erwähnt habe, können Sie die "Anführungszeichen in einer Erweiterung enthalten, die selbst in "Anführungszeichen gesetzt ist.

CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""

Sie können das "mit einem \Backslash innerhalb der angegebenen "Zeichenfolge umgehen.

CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'

Sie können Anführungszeichenstile abwechseln und verketten, um das gewünschte Endergebnis zu erzielen , wie oben unter @jimmij angegeben .

CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )

Sie können sowohl die Generierung als auch die $IFSAufteilung von Dateinamen deaktivieren, $expansionsodass Sie die Anführungszeichen überhaupt nicht zitieren müssen, und daher nur die Anführungszeichen zitieren. Das ist wahrscheinlich übertrieben.

Zuletzt gibt es eine andere Art von Shell-Zitat, die verwendet werden könnte. Wie bereits erwähnt, wird die sh -c "$scriptlet"Form des Shell-Aufrufs häufig verwendet, um das Skript einer Shell in der Befehlszeile bereitzustellen. Wenn es jedoch $scriptletkompliziert wird - beispielsweise wenn Anführungszeichen andere Anführungszeichen enthalten müssen - kann es oft vorteilhaft sein, ein Here-Dokument zu verwenden und sh -sstattdessen - wo die Shell speziell angewiesen wird , den Positionsparametern alle folgenden Operanden zuzuweisen, wie dies in einem -cFall der Fall wäre und doch auch sein Skript zu entnehmen stdin.

Wenn Ihr Befehl Anführungszeichen auf diese Weise interpretieren muss, würde ich es besser in Betracht ziehen, wenn dies in einer Dateieingabe möglich wäre. Beispielsweise:

CLUSTER=cl1
command --stdin <<-SCRIPT
    cluster="$CLUSTER"
SCRIPT

Wenn Sie das Trennzeichen von a nicht zitieren, werden <<here-documentalle Inhalte fast genau so behandelt, als wären sie in "weichen Anführungszeichen gesetzt worden - mit der Ausnahme, dass "doppelte Anführungszeichen selbst nicht speziell behandelt werden. Und wenn wir catstattdessen das Obige ausführen mit :

CLUSTER=cl1
cat <<-SCRIPT
        cluster="$CLUSTER"
SCRIPT

... es druckt ...

cluster="cl1"
mikeserv
quelle
1

Wie mikeserv schrieb:

 CLUSTER='"cl1"'; command -p "cluster=$CLUSTER" 

„Double - Zitat“ jeder wörtlich , die Leerzeichen / Metazeichen und enthält jede Expansion: "$var", "$(command "$var")", "${array[@]}", "a & b". Verwendung 'single quotes'für Code oder Literal $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. Siehe
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words

Gilles Quenot
quelle
Du hast recht, danke. Aber was ist mit Automatisierung? Angenommen, ich möchte CLUSTER lesen? Ich werde wieder mit dem gleichen Problem stecken bleiben: Variable in einfachen Anführungszeichen
Mohamad-Jaafar NEHME
@Moi - Automatisierung ist keine große Sache, obwohl Sie die Variable der "Zeichen bereinigen müssen - nur die erste und die letzte sollten ausreichen. Das eigentliche Problem hierbei ist, dass Ihre App Zitate in einem Argument interpretiert. Das Interpretieren eines Zitats in einem Argument ist fast nie eine gute Idee, da ein Zitat nur ein Mittel zur Abgrenzung eines Arguments sein sollte - und beim Aufrufen wird die Abgrenzung \0NULin jedem Fall von s behandelt . Wahrscheinlich gibt es eine bessere Möglichkeit, die gewünschten Informationen an die App zu übergeben? Wie ein command --'script=/path/to/some/file'oder so?
Mikeserv