Ich möchte einen Befehl aus einem Bash-Skript ausführen, das einfache Anführungszeichen und einige andere Befehle in einfachen Anführungszeichen und einer Variablen enthält.
z.B repo forall -c '....$variable'
In diesem Format $
wird maskiert und die Variable wird nicht erweitert.
Ich habe die folgenden Variationen 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 ersetze, wird der Befehl einwandfrei ausgeführt.
Bitte sag mir, wo ich falsch liege.
repo forall -c ' ...before... '"$variable"' ...after...'
bash
isst einfache Anführungszeichen. Entweder sind Sie nicht inbash
oder einfache Anführungszeichen sind nicht Teil desrepo
Befehls.Antworten:
In einfachen Anführungszeichen bleibt ausnahmslos alles buchstäblich erhalten.
Das heißt, Sie müssen die Anführungszeichen schließen, etwas einfügen und dann erneut eingeben.
Die Wortverkettung erfolgt einfach durch Nebeneinander. Wie Sie überprüfen können, ist jede der obigen Zeilen ein einzelnes Wort für die Shell. Anführungszeichen (einfache oder doppelte Anführungszeichen, je nach Situation) isolieren keine Wörter. Sie werden nur verwendet, um die Interpretation verschiedener Sonderzeichen wie Leerzeichen
$
,;
... zu deaktivieren. Ein gutes Tutorial zum Zitieren finden Sie in Mark Reeds Antwort. Ebenfalls relevant: Welche Zeichen müssen in Bash maskiert werden?Verketten Sie keine von einer Shell interpretierten Zeichenfolgen
Sie sollten das Erstellen von Shell-Befehlen durch Verketten von Variablen unbedingt vermeiden. Dies ist eine schlechte Idee, ähnlich der Verkettung von SQL-Fragmenten (SQL-Injection!).
Normalerweise ist es möglich, Platzhalter im Befehl zu haben und den Befehl zusammen mit Variablen anzugeben, damit der Angerufene sie aus der Liste der Aufrufargumente empfangen kann.
Zum Beispiel ist das Folgende sehr unsicher. TUN SIE DAS NICHT
Wenn der Inhalt von
$myvar
nicht vertrauenswürdig ist, ist hier ein Exploit:Verwenden Sie anstelle des obigen Aufrufs Positionsargumente. Der folgende Aufruf ist besser - er kann nicht ausgenutzt werden:
Beachten Sie die Verwendung einzelner Häkchen in der Zuordnung zu
script
, was bedeutet, dass dies wörtlich genommen wird, ohne variable Erweiterung oder irgendeine andere Form der Interpretation.quelle
"some"thing' like'this
ist alles ein Wort für die Shell. Anführungszeichen beenden nichts, was das Parsen betrifft, und es gibt keine Möglichkeit für einen Befehl, der von der Shell aufgerufen wird , zu sagen, was wie zitiert wurde.Dem
repo
Befehl ist es egal, welche Art von Anführungszeichen er erhält. Wenn Sie eine Parametererweiterung benötigen, verwenden Sie doppelte Anführungszeichen. Wenn dies bedeutet, dass Sie eine Menge Dinge rückgängig machen müssen, verwenden Sie für das meiste einfache Anführungszeichen und brechen Sie dann aus diesen heraus und gehen Sie für den Teil, in dem die Erweiterung stattfinden soll, in Doppel.Erklärung folgt, wenn Sie interessiert sind.
Wenn Sie einen Befehl über die Shell ausführen, empfängt dieser Befehl als Argumente ein Array von nullterminierten Zeichenfolgen. Diese Zeichenfolgen können absolut jedes Nicht-Null-Zeichen enthalten.
Wenn die Shell dieses Array von Zeichenfolgen über eine Befehlszeile erstellt, werden einige Zeichen speziell interpretiert. Dies soll die Eingabe von Befehlen erleichtern (tatsächlich möglich machen). Beispielsweise geben Leerzeichen normalerweise die Grenze zwischen Zeichenfolgen im Array an. Aus diesem Grund werden die einzelnen Argumente manchmal als "Wörter" bezeichnet. Ein Argument kann jedoch Leerzeichen enthalten. Sie brauchen nur eine Möglichkeit, der Shell zu sagen, dass Sie das wollen.
Sie können einen Backslash vor einem beliebigen Zeichen (einschließlich Leerzeichen oder einem anderen Backslash) verwenden, um die Shell anzuweisen, dieses Zeichen wörtlich zu behandeln. Aber während Sie so etwas tun können:
echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier
... es kann lästig werden. Die Shell bietet also eine Alternative: Anführungszeichen. Diese kommen in zwei Hauptsorten.
Doppelte Anführungszeichen werden als "Gruppieren von Anführungszeichen" bezeichnet. Sie verhindern, dass Platzhalter und Aliase erweitert werden, aber meistens dienen sie dazu, Leerzeichen in ein Wort aufzunehmen. Andere Dinge wie die Parameter- und Befehlserweiterung (die Art von Dingen, die durch a signalisiert werden
$
) passieren immer noch. Und wenn Sie ein wörtliches doppeltes Anführungszeichen in doppelten Anführungszeichen haben möchten, müssen Sie es natürlich umkehren:echo "\"Thank you. That'll be \$4.96, please,\" said the cashier"
Einfache Anführungszeichen sind drakonischer. Alles zwischen ihnen wird buchstäblich genommen, einschließlich Backslashes. Es gibt absolut keine Möglichkeit, ein wörtliches einfaches Anführungszeichen in einfache Anführungszeichen zu setzen.
Glücklicherweise sind Anführungszeichen in der Shell keine Worttrennzeichen . an sich beenden sie kein Wort. Sie können innerhalb desselben Wortes in Anführungszeichen ein- und ausgehen, auch zwischen verschiedenen Arten von Anführungszeichen, um das gewünschte Ergebnis zu erzielen:
echo '"Thank you. That'\''ll be $4.96, please," said the cashier'
Das ist also einfacher - viel weniger Backslashes, obwohl die Sequenz "Close-Single-Quote", "Backslashed-Literal-Single-Quote", "Open-Single-Quote" gewöhnungsbedürftig ist.
Moderne Shells haben einen weiteren Anführungszeichenstil hinzugefügt, der nicht im POSIX-Standard festgelegt ist. Dem führenden einfachen Anführungszeichen wird ein Dollarzeichen vorangestellt. So zitierte Zeichenfolgen folgen ähnlichen Konventionen wie Zeichenfolgenliterale in der Programmiersprache ANSI C und werden daher manchmal als "ANSI-Zeichenfolgen" und das
$'
...'
Paar "ANSI-Anführungszeichen" bezeichnet. Innerhalb solcher Zeichenfolgen gilt der obige Hinweis, dass Backslashes buchstäblich verwendet werden, nicht mehr. Stattdessen werden sie wieder zu etwas Besonderem. Sie können nicht nur ein wörtliches einfaches Anführungszeichen oder einen umgekehrten Schrägstrich einfügen, indem Sie ihm einen umgekehrten Schrägstrich voranstellen, sondern die Shell erweitert auch die\n
Escapezeichen\t
für ANSI C-Zeichen (z. B. für eine neue Zeile, für Tabulatoren und\xHH
für das Zeichen mit HexadezimalcodeHH
). Andernfalls verhalten sie sich jedoch wie Zeichenfolgen in einfachen Anführungszeichen: Es findet keine Parameter- oder Befehlsersetzung statt:Es ist wichtig zu beachten, dass die einzelne Zeichenfolge, die als Argument für den
echo
Befehl empfangen wird , in all diesen Beispielen genau dieselbe ist . Nachdem die Shell eine Befehlszeile analysiert hat, kann der ausgeführte Befehl nicht mehr angeben, was wie angegeben wurde. Auch wenn es wollte.quelle
$'string'
Format POSIX kompatibel? Gibt es auch einen Namen dafür?$'string'
ist eine Nicht-POSIX-Erweiterung, die ich als "ANSI-Zeichenfolgen" bezeichnet habe. Ich habe diese Fakten in die Antwort aufgenommen. Solche Zeichenfolgen funktionieren in den meisten modernen Bourne-kompatiblen Shells: bash, dash, ksh (sowohl AT & T als auch PD) und zsh unterstützen sie alle.Unten ist, was für mich funktioniert hat -
quelle
QUOTE
einer separaten Variablen ist völlig überflüssig. einfache Anführungszeichen in doppelten Anführungszeichen sind nur reguläre Zeichen. (Verwenden Sie auch keine Großbuchstaben für Ihre privaten Variablen.)EDIT: (Gemäß den fraglichen Kommentaren :)
Ich habe mich seitdem damit befasst. Ich hatte das Glück, dass ich Repo herumliegen hatte. Trotzdem ist mir nicht klar, ob Sie Ihre Befehle mit Gewalt in einfache Anführungszeichen setzen müssen. Ich habe mir die Repo-Syntax angesehen und glaube nicht, dass Sie das brauchen. Sie können doppelte Anführungszeichen um Ihren Befehl verwenden und dann alle einfachen und doppelten Anführungszeichen verwenden, die Sie benötigen, vorausgesetzt, Sie entkommen doppelten Anführungszeichen.
quelle
benutze einfach printf
anstatt
Verwenden Sie printf, um das Variablentoken durch die erweiterte Variable zu ersetzen.
Zum Beispiel:
quelle
printf
kauft Ihnen hier nicht wirklich etwas, und wenn Sie die Befehlssubstitution nicht zitieren, entstehen neue Anführungsprobleme.Variablen können einfache Anführungszeichen enthalten.
quelle
"$myvar"
doppelte Anführungszeichen setzen.Geht das für dich?
quelle