ubuntuusers.de

Bash: awk --> in eine Datei schreiben

Status: Gelöst | Ubuntu-Version: Xubuntu 16.04 (Xenial Xerus)
Antworten |

KeyzerSoze

Anmeldungsdatum:
28. September 2014

Beiträge: 120

Hallo ubuntuusers,

ich würde mir gerne mittels des awk-Programmes ein Dokument erzeugen:

#! /bin/bash
#variable=grep 'wert' readme |rev| cut -d" " -f1|rev # --> liefert 0.68
for ii in {1..2}
do
	awk -i inplace  'BEGIN{ printf "Hallo";}{printf "%s ",$1; b++} b==5 {print ""; b=0} END {printf "\nBye\n"}' data$ii
done

Und zwar liest mein Programm mittels

 {printf "%s ",$1; b++} b==5 {print ""; b=0} 

die 1. Spalte meines Datafiles aus und verwandelt sie in Zeilen der Länge 5. Das alles funktioniert ohne Probleme.

Jedoch hätte ich noch gerne an den Beginn des Datafiles Hallo geschrieben und ans Ende Bye. Das funktioniert leider nicht, diese beiden Strings werden im Terminal angezeigt und nicht im file, wo liegt mein Denkfehler, bzw. was muss ich ändern?

Dann, wenn das klappt, würde ich noch gerne eine Variable im Datafile an den Anfang des Dokumentes printen: ich habe gelesen, dass man dafür den Flag -v setzen muss und die Variable nach diesem Schema einfügen kann (weil es bei mir noch nicht klappt, habe ich die Variable auskommentiert):

awk -v var="$variable" 'BEGIN {print var}'

Kann ich dann auch mit awk Rechenoperationen durchführen, z.B.

 BEGIN {print var/3} 

? Das wäre mir sehr wichtig!

Danke im Voraus!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13215

KeyzerSoze schrieb:

ich würde mir gerne mittels des awk-Programmes ein Dokument erzeugen:

#! /bin/bash
#variable=grep 'wert' readme |rev| cut -d" " -f1|rev # --> liefert 0.68
for ii in {1..2}
do
	awk -i inplace  'BEGIN{ printf "Hallo";}{printf "%s ",$1; b++} b==5 {print ""; b=0} END {printf "\nBye\n"}' data$ii
done

Du greifst auf zwei Dateien zu, die Du veränderst. Du erzeugst nicht ein Dokument. Was willst Du nun genau?

Jedoch hätte ich noch gerne an den Beginn des Datafiles Hallo geschrieben und ans Ende Bye. Das funktioniert leider nicht, diese beiden Strings werden im Terminal angezeigt und nicht im file, wo liegt mein Denkfehler, bzw. was muss ich ändern?

Da Du anscheinend an den Anfang jeder Datei etwas schreiben willst und gawk nutzt, wäre "BEGINFILE" wohl das geeignete Mittel anstatt "BEGIN".

Dann, wenn das klappt, würde ich noch gerne eine Variable im Datafile an den Anfang des Dokumentes printen: ich habe gelesen, dass man dafür den Flag -v setzen muss und die Variable nach diesem Schema einfügen kann (weil es bei mir noch nicht klappt, habe ich die Variable auskommentiert):

awk -v var="$variable" 'BEGIN {print var}'

Wo ist das Problem?

1
2
$ awk -v foo=123 'BEGIN {print foo}'
123

Kann ich dann auch mit awk Rechenoperationen durchführen, z.B.

 BEGIN {print var/3} 

? Das wäre mir sehr wichtig!

Probier es halt aus. Die Manpage ist auch hilfreich.

KeyzerSoze

(Themenstarter)

Anmeldungsdatum:
28. September 2014

Beiträge: 120

Du greifst auf zwei Dateien zu, die Du veränderst. Du erzeugst nicht ein Dokument. Was willst Du nun genau?

Sorry für die ungenaue Formulierung, ich meinte ein Dokument pro festes ii bei der for-Schleife. Insgesamt also 2 Dokumente.

Da Du anscheinend an den Anfang jeder Datei etwas schreiben willst und gawk nutzt, wäre "BEGINFILE" wohl das geeignete Mittel >anstatt "BEGIN".

Vielen Dank für diese Infos, sie waren sehr hilfreich: gawk kannte ich gar nicht und beginfile ist mir auch neu.

Der Rest hat auch noch gut geklappt, das einzige, was mich noch nicht vollständig zufrieden stellt, ist dass

awk -v var="$variable" 'BEGIN {print var}'

bei mir in der for Schleife steht und so jedesmal die Variable (bei mir grep) neu ge'grept' wird, obwohl ein einziges Mal ausreichen würde. Aber wie man die Variablen von gawk "trennt", werde ich schon noch herausfinden ☺

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13215

KeyzerSoze schrieb:

Da Du anscheinend an den Anfang jeder Datei etwas schreiben willst und gawk nutzt, wäre "BEGINFILE" wohl das geeignete Mittel >anstatt "BEGIN".

Vielen Dank für diese Infos, sie waren sehr hilfreich: gawk kannte ich gar nicht und beginfile ist mir auch neu.

Achte auf die Großschreibung.

Der Rest hat auch noch gut geklappt, das einzige, was mich noch nicht vollständig zufrieden stellt, ist dass

Wie sieht denn Deine Lösung nun aus?

awk -v var="$variable" 'BEGIN {print var}'

bei mir in der for Schleife steht und so jedesmal die Variable (bei mir grep) neu ge'grept' wird, obwohl ein einziges Mal ausreichen würde. Aber wie man die Variablen von gawk "trennt", werde ich schon noch herausfinden ☺

Der Sinn Deiner Worte ist dunkel.

PS: Bitte achte darauf Zitate in Takt zu lassen. Die Header helfen auch Lesern, die Bezüge der Beiträge richtig zu nachzuverfolgen.

KeyzerSoze

(Themenstarter)

Anmeldungsdatum:
28. September 2014

Beiträge: 120

Hallo, das ist meine Lösung:

for ii in $(eval echo "{1..$( head -n 1 somefile| wc -w )}")
do
	
 gawk -i inplace -v "var1=$(grep -i  'someword' somefile|rev|cut -d" " -f1|rev)" -v "var2=$(grep -i 'someotherword' someotherfile|rev|cut -d" " -f1|rev)" 'BEGINFILE{ printf "BEGIN_INFO:\n"; printf var1 ; printf "\n"; printf var2; printf "\n";}{printf " %s",$1; b++} b==5 {print ""; b=0} ENDFILE {printf "\nEND"}' data$ii.txt

done

Was ich meinte, ist, dass die beiden Variablen var1 und var2 für jedes ii neu ausgerechnet/gesucht werden, obwohl sie eigentlich konstant sind und einmaliges Ausrechnen genügen würde.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13215

KeyzerSoze schrieb:

Hallo, das ist meine Lösung:

for ii in $(eval echo "{1..$( head -n 1 somefile| wc -w )}")
do
	
 gawk -i inplace -v "var1=$(grep -i  'someword' somefile|rev|cut -d" " -f1|rev)" -v "var2=$(grep -i 'someotherword' someotherfile|rev|cut -d" " -f1|rev)" 'BEGINFILE{ printf "BEGIN_INFO:\n"; printf var1 ; printf "\n"; printf var2; printf "\n";}{printf " %s",$1; b++} b==5 {print ""; b=0} ENDFILE {printf "\nEND"}' data$ii.txt

done

Was ich meinte, ist, dass die beiden Variablen var1 und var2 für jedes ii neu ausgerechnet/gesucht werden, obwohl sie eigentlich konstant sind und einmaliges Ausrechnen genügen würde.

Und, warum machst Du das dann?

Es erschließt sich mir auch nicht, warum Du erst die Wörter in der ersten Zeile von "somefile" zählst und dann gar nichts mit diesen Wörtern machst. Darüber hinaus ist die Verwendung von eval hier völlig überflüssig. Da kann man besser eine for-Schleife nehmen:

1
2
3
4
5
words=$( head -n 1 somefile | wc -w )

for ((i=1; i <= words; ++i)); do
...
done

KeyzerSoze

(Themenstarter)

Anmeldungsdatum:
28. September 2014

Beiträge: 120

Und, warum machst Du das dann?

Ich habe sehr lange probiert, wie ich die Variablen in gawk einbauen kann. Diese Variante war die erste (und bis jetzt auch die einzige), die funktioniert, jedoch schaue ich morgen nochmal, ob ich die Variablen aus der for - Schleife herausnehmen kann. Allzu schwer sollte das ja nicht sein, nachdem ich jetzt weiß, wie es ungefähr gehen sollte.

Darüber hinaus ist die Verwendung von eval hier völlig überflüssig. Da kann man besser eine for-Schleife nehmen

Das sehe ich ein, darauf bin ich leider selbst nicht gekommen.

Es erschließt sich mir auch nicht, warum Du erst die Wörter in der ersten Zeile von "somefile" zählst und dann gar nichts mit diesen Wörtern machst.

Naja, es sind eigentlich Zahlen, ich muss nur deren Anzahl abzählen, um zu wissen, wie viele data*.txt files existieren. Vielleicht kommt das hier nicht klar heraus, weil ich versucht habe, ein Minimalbeispiel zu erstellen und so einige Befehle (die funktionieren und nicht weiter für dieses Thema interessant sind) entfernt habe.

Antworten |