Nach einer Antwort zum Stackoverflow ist das Einkapseln von Bash-Variablen in doppelte Anführungszeichen meines Erachtens eine ziemlich sichere Methode, um Benutzereingaben zu bereinigen.
Was ist mit awk-Variablen? Zum Beispiel, wenn ich so etwas habe wie:
awk -v SOURCEIP="$SOURCEIP" -v REVERSEDNS="$REVERSEDNS" '{
gsub(/^_TMPSOURCEIP_/, SOURCEIP);
gsub(/^_TMPREVERSEDNS_/, REVERSEDNS);
print
}' /home/foo/footemplate
Sollte ich die Variable in den gsub-Zeilen in Anführungszeichen setzen? So würde es dann aussehen:
awk -v SOURCEIP="$SOURCEIP" -v REVERSEDNS="$REVERSEDNS" '{
gsub(/^_TMPSOURCEIP_/, "SOURCEIP");
gsub(/^_TMPREVERSEDNS_/, "REVERSEDNS");
print
}' /home/foo/footemplate
Oder macht das keinen Unterschied?
Antworten:
Diese beiden Beispiele zeigen den Unterschied:
Wenn
VAR
nicht in Anführungszeichen gesetzt ist, wirdawk
es als Variable mit dem Wert behandeltsome "text"
. WennVAR
es in Anführungszeichen steht, behandelt awk es als dreistellige Zeichenfolge.MEHR:
bash
hat Desinfektionsprobleme. Erwägen:Das obige wird gelöscht
important_file
. Auf diese Weisebash
ist es wie eine Makrosprache: Sie ersetzt eine Variable und versucht dann, das Ergebnis auszuführen.awk
ist anders. Erwägen:awk
behandeltVAR
wie bloßer Text, nicht wie mögliche auszuführende Befehle.Probleme können jedoch auftreten, wenn man
bash
dasawk
Skript ändern lässt . In meinen obigen Beispielen waren dieawk
Skripte alle in einfachen Anführungszeichen. Das verhindert, dass manbash
sich mit ihnen anlegen kann.quelle
VAR='blah; echo $1'
ist auch für die Shell kein Problem (es sei denn, Sie verwendeneval
). Es ist keine Makrosprache (außer bis zu einem gewissen Grad alias Erweiterung)(OK, tut mir leid, ich habe Ihre Frage zu schnell gelesen, daher ist ein Teil meiner Antwort etwas nebensächlich und lässt sie immer noch so, wie sie für Sie oder andere nützlich sein kann.)
Hier sind einige Dinge zu beachten.
Zitieren von Shell- Variablen
Wenn Sie eine Variable in POSIX-Shells nicht in Anführungszeichen setzen (in Listenkontexten, wie in Argumenten für einen Befehl), ist dies nicht
awk
der Operator split + glob.Wenn Sie tun:
Wo
$var
ist* *
.Bitten Sie die Shell nicht, den Inhalt
$var
basierend auf dem Wert der$IFS
speziellen Shell-Variablen zu teilen , standardmäßig auf Leerzeichen. Das gibt uns alsofoo=*
und*
und führt Globbing für jeden von diesen durch, dh erweitertfoo=*
auf alle Dateinamen im aktuellen Verzeichnis, die mitfoo=
und*
auf alle nicht versteckten Dateinamen beginnen.Sie sollten also fast immer Ihre Shell- Variablen zitieren , unabhängig davon, ob es sich um Argumente handelt
awk
oder nicht. Dies gilt auch für die Shell-Befehlsersetzung (`...`
und$(...)
) und die Shell-Arithmetik-Erweiterung ($((...))
).Daten so wie sie sind an übergeben
awk
Das andere Problem ist, dass
awk
(nicht die Shell) Backslash-Escape-Sequenzen in den Zuweisungen von Variablen wie-v var=value
(und mit GNUawk
4.2 oder höher, wenn der Wert mit beginnt@/
und endet/
, als regulärer Variablentyp behandelt wird ) erweitert wird.Setzt beispielsweise
-v var='\n/\n/'
den Inhalt derawk
var
Variablen auf<newline>/<newline>/
nicht\n/\n/
. Dies gilt auch fürawk
Variablen, die definiert sind als:Um Daten zu übergeben,
awk
ohne dass diese Erweiterung durchgeführt wird, können Sie die ArraysENVIRON
oderARGV
awk verwenden:(oben ist es eine Shell-Variablenzuweisung (zu einer Nicht-Array-Variablen), daher kann es keine Aufteilung + Glob geben, was einer der seltenen Fälle ist, in denen Sie die Anführungszeichen um Variablen weglassen können.)
oder:
Anführungszeichen und
awk
VariablenDieser Split + Glob ist nur eine Shell- (Fehl-) Funktion. Die
awk
Sprache ist eine ganz andere Sprache.In
awk
beziehen sich Variablen auf avarname
, not$varname
und Anführungszeichen werden verwendet, um Zeichenfolgen einzuführen. So"varname"
ist dievarname
Zeichenfolge, währendvarname
auf die Variable verweist.Bereinigen von Variablen, um Code-Injection zu vermeiden
Genau genommen ist das Zitieren von Shell-Variablen keine Bereinigung, es zitiert nicht die Variablen , die den Operator split + glob verwenden. Während Sie in den meisten Sprachen Anführungszeichen um feste Zeichenfolgen setzen, ist es in Shells umgekehrt: Alles ist Zeichenfolge, und Anführungszeichen werden verwendet, um ein bestimmtes Verhalten zu verhindern, und insbesondere Variablen sollten fast immer in Anführungszeichen gesetzt werden (eine schlechte Entwurfsentscheidung dieser Art) machte in der Bourne-Muschel in den 70er Jahren Sinn, ist aber ein Hindernis für moderne Muscheln, da
zsh
es die einzige Muschel ist, die dies teilweise behoben hat.Die Shell oder awk wertet / interpretiert keinen in ihrer eigenen Variablen gespeicherten Code aus, es sei denn, Sie weisen sie an.
Bewirkt nicht, dass der Inhalt der Variablen als Shell-Code ausgewertet wird (obwohl der erste Code aufgeteilt und globalisiert wird, was schwerwiegende Folgen haben kann (z. B. mit
var='/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*'
). Sie benötigen:damit es als Shell-Code ausgewertet / interpretiert wird.
awk
hat keine solcheeval
Funktion.perl
Ichpython
mache.Achten Sie jedoch auf Kreuzkontaminationen. Sie können die Shell-Variablendaten (in Shell- Variablen) als Code ausführen lassen, um Folgendes auszuführen
awk
:wäre gefährlich, wenn die
$var
Shell- Variable zum Beispiel enthält:weil die Shell dann ausführen würde:
Oder umgekehrt:
Wo
awk
würde eine Shell laufen als:für jede Zeile von
file
(und überlegen Sie, was eine Zeile wie; rm -rf /
tun würde).Es ist nicht nur zwischen
awk
undsh
. Sie müssen vorsichtig sein, wenn variable / unkontrollierte Daten von einem anderen Interpreter als Code ausgewertet werden. Beispiele sind:sed
's Sprache ist begrenzt, aber es kann immer noch schaden, wie beiregexp='//;w /etc/passwd; s/
'.Oder:
Um diese Probleme zu vermeiden, gibt es zwei allgemeine Ansätze:
Konvertieren Sie die Variable von einem Interpreter in den anderen. Das funktioniert für die Shell -> awk oder find -> sh case oben. Wie Veränderung:
zu:
Und:
zu:
Aber das funktioniert nicht für die Shell -> sed oder awk -> Shell Fälle.
Wenn 1 nicht möglich ist, müssen Sie die Variablen bereinigen, um die möglicherweise problematischen Zeichen zu entfernen oder zu entfernen. Im,
Sie müssen in
$0
etwas konvertieren , das für die Shell eine saubere Zeichenfolge ist. Eine Möglichkeit besteht darin, jedem Zeichen einen Backslash voranzustellen, dies funktioniert jedoch nicht für Zeilenumbrüche (hier kein Problem). Eine andere Möglichkeit besteht darin, die Zeichenfolge in einfache Anführungszeichen zu setzen und jedes einzelne Anführungszeichen zu umgehen.quelle
$SOURCEIP
istrm -fr /
. Wenn ich das an awk via weitergebeawk -v AWKVAREXAMPLE="$SOURCEIP"
und später awk einen gsub machen lasse,gsub(/^_TARGETSTRING_/, AWKVAREXAMPLE);
würde das irgendwann in die Shell "lecken" und alles zerstören?awk
eine Shell aufgerufen und als Code übergeben würde, den sie wie folgt interpretieren könnte:awk '{system("echo " var)}'
(wovar
ist;rm -rf /
), woawk
ruft auf["sh", "-c", "echo; rm -rf /"]
oderawk '{print | "tr " v1 " " v2}'
wohinawk
leitet die Ausgabe weiter["sh", "-c", "tr content-of-v1 content-of-v2"]
.awk "{print \"$shell_variables\"}"
Wie dort wird der Inhalt der Shell-Variablen als awk-Code interpretiert.Wenn Sie eine Awk-Variable an das System übergeben , müssen Sie sie in Anführungszeichen setzen:
Beispiel:
Quelle
quelle