Ich habe einige Möglichkeiten gefunden, externe Shell-Variablen an ein awk
-Skript zu übergeben, aber ich bin verwirrt über '
und "
.
Zuerst habe ich es mit einem Shell-Skript versucht:
$ v=123test
$ echo $v
123test
$ echo "$v"
123test
Dann versuchte ich es mit awk:
$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123
Worin besteht der Unterschied?
Zuletzt habe ich dies versucht:
$ awk 'BEGIN{print " '$v' "}'
$ 123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1: ^ unexpected newline or end of string
Ich bin darüber verwirrt.
Shell-Variablen in
awk
setzenkann auf verschiedene Arten erfolgen. Einige sind besser als andere. Dies sollte die meisten von ihnen abdecken. Wenn Sie einen Kommentar haben, hinterlassen Sie ihn bitte unten.
-v
(Der beste Weg, am besten portabel)Benutzen Sie die -v
Option: (P.S. Benutzen Sie ein Leerzeichen nach -v
oder es wird weniger portabel sein. Z.B., awk -v var=
nicht awk -vvar=
)
variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two
Dies sollte mit den meisten awk
kompatibel sein, und die Variable ist auch im BEGIN
-Block verfügbar:
Wenn Sie mehrere Variablen haben:
awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'
Warnung. Wie Ed Morton schreibt, werden Escape-Sequenzen interpretiert, so dass \t
zu einem echten tab
wird und nicht zu \t
, wenn das das ist, wonach Sie suchen. Kann durch die Verwendung von ENVIRON[]
oder den Zugriff über ARGV[]
gelöst werden.
PS Wenn Sie drei senkrechte Striche als Trennzeichen |||
mögen, können diese nicht escaped werden, also verwenden Sie -F"[|][|][|][|]"
Beispiel für das Abrufen von Daten aus einem Programm/Funktion inn to awk
(hier wird das Datum verwendet)
awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'
Hier bekommen wir die Variable nach dem awk
Code. Das funktioniert gut, solange man die Variable nicht im BEGIN
-Block braucht:
variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file
Dies funktioniert auch mit mehreren Variablen awk '{print a,b,$0}' a="$var1" b="$var2" file`
Die Verwendung von Variablen auf diese Weise funktioniert nicht im BEGIN
-Block:
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
Variable können auch zu awk
hinzugefügt werden, indem man einen here-string von Shells benutzt, die sie unterstützen (einschließlich Bash):
awk '{print $0}' <<< "$variable"
test
Dies ist dasselbe wie:
printf '%s' "$variable" | awk '{print $0}'
P.S. Dies behandelt die Variable wie eine Dateieingabe.
ENVIRON
EingabeWie TrueY schreibt, können Sie ENVIRON
verwenden, um Umgebungsvariablen auszugeben.
Wenn Sie eine Variable setzen, bevor Sie AWK starten, können Sie sie wie folgt ausgeben:
X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash
ARGV
-EingabeWie Steven Penny schreibt, kann man ARGV
benutzen, um die Daten in awk zu bekommen:
v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data
Um die Daten in den Code selbst zu bekommen, nicht nur in den BEGIN:
v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test
Man kann eine Variable innerhalb des awk
-Codes verwenden, aber das ist unübersichtlich und schwer zu lesen, und wie Charles Duffy
anmerkt, kann diese Version auch ein Opfer von Code-Injection werden. Wenn jemand schlechtes Zeug in die Variable einfügt, wird es als Teil des awk
Codes ausgeführt.
Das funktioniert, indem man die Variable innerhalb des Codes extrahiert, so dass sie Teil des Codes wird.
Wenn Sie einen awk
machen wollen, der sich dynamisch mit der Verwendung von Variablen ändert, können Sie das auf diese Weise tun, aber verwenden Sie es NICHT für normale Variablen.
variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
Hier ist ein Beispiel für Code-Injektion:
variable='line one\nline two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000
Man kann auf diese Weise viele Befehle zu awk
hinzufügen. Man kann es sogar mit ungültigen Befehlen zum Absturz bringen.
Es ist immer gut, die Variable "$variable"
in Anführungszeichen zu setzen.
Andernfalls werden mehrere Zeilen als eine einzige lange Zeile eingefügt.
Beispiel:
var="Line one
This is line two"
echo $var
Line one This is line two
echo "$var"
Line one
This is line two
Andere Fehler können Sie ohne Anführungszeichen erhalten:
variable="line one\nline two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ backslash not last character on line
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ syntax error
Und mit einfachem Anführungszeichen wird der Wert der Variablen nicht erweitert:
awk -v var='$variable' 'BEGIN {print var}'
$variable
Verwenden Sie eine der beiden, je nachdem, wie Sie Backslashes in den Shell-Variablen behandeln wollen (avar
ist eine awk-Variable, svar
ist eine Shell-Variable):
awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
Siehe http://cfajohnson.com/shell/cus-faq-2.html#Q24 für Details und andere Optionen. Die erste Methode oben ist fast immer die beste Option und hat die offensichtlichste Semantik.
Sie können die Befehlszeilenoption -v
mit einem Variablennamen (v
) und einem Wert (=
) der Umgebungsvariablen ("${v}"
) übergeben:
% awk -vv="${v}" 'BEGIN { print v }'
123test
Oder um es deutlicher zu machen (mit viel weniger v
):
% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test