Gibt es eine Möglichkeit, eine Variable in meiner aktuellen Shell aus awk
zu setzen?
Ich möchte einige Dateien bearbeiten und Daten ausdrucken. Da ich die gesamte Datei durchgelesen habe, möchte ich die Anzahl der Zeilen speichern - in diesem Fall FNR
.
Das passiert, obwohl ich keine Möglichkeit finde, eine Shell-Variable mit FNR
value zu setzen. Wenn nicht, müsste ich die Variable FNR
aus meiner Ausgabedatei lesen, um num_lines
mit dem Wert FNR
festzulegen.
Ich habe einige Kombinationen mit awk 'END{system(...)}'
ausprobiert, konnte es aber nicht schaffen. Irgendein Weg um dieses herum?
$ echo "$var"
$ declare $( awk 'BEGIN{print "var=17"}' )
$ echo "$var"
17
Deshalb sollten Sie declare anstelle von eval verwenden:
$ eval $( awk 'BEGIN{print "echo \"removing all of your files, ha ha ha....\""}' )
removing all of your files, ha ha ha....
$ declare $( awk 'BEGIN{print "echo \"removing all of your files\""}' )
bash: declare: `"removing': not a valid identifier
bash: declare: `files"': not a valid identifier
Beachten Sie im ersten Fall, dass eval die von awk ausgegebenen Zeichenfolgen ausführt, was aus Versehen eine sehr schlechte Sache sein könnte!
Hier ist ein anderer Weg.
Dies ist besonders nützlich, wenn Sie die values Ihrer Variablen in einer single -Variable haben und diese aufteilen möchten. Beispielsweise haben Sie eine Liste von Werten aus einer einzelnen Zeile in einer Datenbank, aus der Sie Variablen erstellen möchten.
val="hello|beautiful|world" # assume this string comes from a database query
read a b c <<< $( echo ${val} | awk -F"|" '{print $1" "$2" "$3}' )
echo $a #hello
echo $b #beautiful
echo $c #world
Wir brauchen in diesem Fall den "Here-String", dh <<<, da der Befehl read nicht aus einer Pipe und stattdessen aus stdin liest
Sie können keine Variablen aus einer Subshell in die übergeordnete Shell exportieren. Sie haben jedoch andere Möglichkeiten, darunter:
Führen Sie die Datei erneut mit AWK durch, um Datensätze zu zählen, und verwenden Sie die Befehlsersetzung, um das Ergebnis zu erfassen. Zum Beispiel:
FNR=$(awk 'END {print FNR}' filename)
wc -l < filename
aufrufen, um Ihre Zählung abzurufen.Eine Warnung für alle, die versuchen, die Erklärung zu verwenden, wie in mehreren Antworten vorgeschlagen.
eval hat dieses Problem nicht.
Wenn der zum Deklarieren von awk (oder einem anderen Ausdruck) bereitgestellte Ergebnis zu einer leeren Zeichenfolge führt, wird die aktuelle Umgebung deklariert .. _ Dies ist fast sicher nicht das, was Sie möchten.
beispiel: Wenn Ihr awk-Muster in der Eingabe nicht vorhanden ist, werden Sie niemals eine Ausgabe drucken. Das Ergebnis ist ein unerwartetes Verhalten.
Ein Beispiel dafür ....
unset var
var=99
declare $( echo "foobar" | awk '/fail/ {print "var=17"}' )
echo "var=$var"
var=99
The current environment as seen by declare is printed
and $var is not changed
Eine geringfügige Änderung, um den zu speichernden Wert in einer awk-Variablen zu speichern und am Ende zu drucken, löst dies ....
unset var
var=99
declare $( echo "foobar" | awk '/fail/ {tmp="17"} END {print "var="tmp}' )
echo "var=$var"
var=
This time $var is unset ie: set to the null string var=''
and there is no unwanted output.
Um dies mit einem passenden Muster zu zeigen
unset var
var=99
declare $( echo "foobar" | awk '/foo/ {tmp="17"} END {print "var="tmp}' )
echo "var=$var"
var=
This time $var is unset ie: set to the null string var=''
and there is no unwanted output.
Machen Sie awk
, um die Zuweisungsaussage auszudrucken:
MYVAR=NewValue
Dann in Ihrem Shell-Skript eval
die Ausgabe Ihres awk
-Skripts:
eval $(awk ....)
# then use $MYVAR
BEARBEITEN: Leute empfehlen die Verwendung von declare
anstelle von eval
, um etwas weniger fehleranfällig zu sein, wenn vom inneren Skript etwas anderes als die Zuordnung gedruckt wird. Es ist nur bash, aber es ist in Ordnung, wenn die Shell ist bash und das Skript #!/bin/bash
hat, die diese Abhängigkeit richtig angibt.
Die eval $(...)
-Variante ist weit verbreitet, wobei bestehende Programme eine Ausgabe generieren, die für eval
, nicht jedoch für declare
geeignet ist (lesspipe
ist ein Beispiel). Deshalb ist es wichtig, es zu verstehen, und die bash-only-Variante ist "zu lokalisiert".
Um hier alles soweit zu synthetisieren, werde ich Ihnen mitteilen, was ich für nützlich halte, um eine Shell-Umgebungsvariable aus einem Skript festzulegen, das eine einzeilige Datei mit awk liest. Natürlich könnte anstelle von /pattern/
ein NR==1
verwendet werden, um die benötigte Variable zu finden.
# export a variable from a script (such as in a .dotfile)
declare $( awk 'NR==1 {tmp=$1} END {print "Shell_VAR=" tmp}' /path/to/file )
export Shell_VAR
Dadurch wird eine massive Ausgabe von Variablen vermieden, wenn ein declare
-Befehl ohne Argumente sowie die Sicherheitsrisiken einer blinden eval
ausgegeben wird.
echo "First arg: $ 1" für ((i = 0; i <$ 1; i ++)); echo "inside" echo "Willkommen $ i times." cat man.xml | awk '{x [NR] = $ 0} END {für (i = 2; i <= NR; i ++) {if (x [i] ~ //) {x [i + 1] = "' $ i" " } print x [i]}} '> $ i.xml done echo "abgeschlossen"