awk
awk
Ich habe eine Datei mit ca 500000 Zeilen.
Die Werte sind Spaltenweise, durch Leerzeichen getrennt.
In der 8. Spalte und in der 12 Spalte sind Angaben die in den unterschiedlichen Zeilen gleich vorkommen.
Diese müssen gezählt werden.
Beispiel
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Lampen 133
Gebaude Schuppen 3 4 5 66 777 Dach 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Birnen 133
Das Ergebnis soll sein:
Dach Lampen 2
Dach Birnen 2
Giebel Birnen 1
Giebel Lampen 1
Ich hoffe mir kann jemand helfen, Danke
Die Werte sind Spaltenweise, durch Leerzeichen getrennt.
In der 8. Spalte und in der 12 Spalte sind Angaben die in den unterschiedlichen Zeilen gleich vorkommen.
Diese müssen gezählt werden.
Beispiel
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Lampen 133
Gebaude Schuppen 3 4 5 66 777 Dach 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Birnen 133
Das Ergebnis soll sein:
Dach Lampen 2
Dach Birnen 2
Giebel Birnen 1
Giebel Lampen 1
Ich hoffe mir kann jemand helfen, Danke
Re: awk
Recht straight-forward in awk (script.awk im folgenden):
Das Sortieren der Einfachheit halber mittels sort über eine Pipe:
Code: Alles auswählen
{
count[$8, $12]++;
}
END {
for (e in count) {
split(e, idx, SUBSEP);
print idx[1] " " idx[2] " " count[e];
}
}
Code: Alles auswählen
awk -f script.awk < data.txt | sort -k 3 -n -r
MfG GoKi
:wq
:wq
Re: awk
Oder mit weniger awk-Gemache:
uniq -c ist in dem Fall ganz brauchbar.
Gruß Cae
Code: Alles auswählen
~/manni$ cat data
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Lampen 133
Gebaude Schuppen 3 4 5 66 777 Dach 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Birnen 133
~/manni$ sort data | uniq -c | awk '{ print $9 " " $13 " " $1 }'
Giebel Birnen 1
Giebel Lampen 1
Dach Birnen 1
Dach Birnen 1
Dach Lampen 2
Gruß Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.
—Bruce Schneier
Re: awk
Verd***mt, du hast Recht.GoKi hat geschrieben:Aber erfüllt nicht ganz die Anforderungen. Du hast zweimal "Dach Birnen 1" im Ergebnis, da sich die Zeilen in $2 unterscheiden.
Dem kann man ja mit nochmal sort, uniq und awk abhelfen… die Sache wird nur leicht unübersichtlich:
Code: Alles auswählen
~/manni$ cat data
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Lampen 133
Gebaude Garage 3 4 5 66 777 Giebel 9 100 111 Lampen 133
Gebaude Schuppen 3 4 5 66 777 Dach 9 100 111 Birnen 133
Gebaude Wohnhaus 3 4 5 66 777 Dach 9 100 111 Birnen 133
~/manni$ sort data | uniq -c | awk '{ print $9 " " $13 " " $1 }' | sort | uniq -c | awk '{ print $2 " " $3 " " $1+$4-1 }'
Dach Birnen 2
Dach Lampen 2
Giebel Birnen 1
Giebel Lampen 1
Gruß Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.
—Bruce Schneier
Re: awk
Alternativ würde sich auch ein am Anfang deiner Pipe anbieten.
Code: Alles auswählen
cut -d" " -f8,12
MfG GoKi
:wq
:wq
Re: awk
Code: Alles auswählen
$ cat data | awk '{print $8,$12}' | sort | uniq -c # | awk '{print $2,$3,$1}'
2 Dach Birnen
2 Dach Lampen
1 Giebel Birnen
1 Giebel Lampen
Code: Alles auswählen
$ time awk '{print $8,$12}' data2 | sort | uniq -c
1678320 Dach Birnen
1678320 Dach Lampen
839160 Giebel Birnen
839160 Giebel Lampen
real 0m8.105s
user 0m8.757s
sys 0m0.788s
aber vielleicht bei sehr, sehr vielen Zeilen auf einzelne Jobs aufteilen?
Code: Alles auswählen
$ cat data | awk '$8=="Dach" && $12=="Birnen"' | wc -l
2
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")
Re: awk
Naja, ab einer gewissen Menge an Daten ist das Sortieren dieser 5.000.000 Zeilen auch nicht zu unterschätzen, sowohl bzgl. Zeit als auch Speicherbedarf.
Ein kurzer Test ergab folgendes (data hat 5.000.006 Zeilen):
Wir sehen da ein paar bekannte Effekte, z.B. cut ist schneller als awk, wenn man nur ein paar Felder extrahieren will.
Also ich bleib beim awk Script, mit mawk statt gawk ist's noch schneller.
Ein kurzer Test ergab folgendes (data hat 5.000.006 Zeilen):
Code: Alles auswählen
$ wc -l data
5000006 data
$ time awk '{print $8,$12}' data | sort | $(uniq -c >/dev/null)
real 0m8.345s
user 0m8.617s
sys 0m0.276s
$ time cut -d" " -f8,12 data | sort | $(uniq -c >/dev/null)
real 0m4.902s
user 0m5.268s
sys 0m0.176s
$ time awk -f script.awk < data | $(sort -k 3 -n -r >/dev/null)
real 0m3.572s
user 0m3.536s
sys 0m0.024s
Also ich bleib beim awk Script, mit mawk statt gawk ist's noch schneller.
MfG GoKi
:wq
:wq
Re: awk
Von der Lesbarkeit finde ich das hier am Schönsten: (auch wenn die awk Variante schneller ist)
Code: Alles auswählen
cut -d " " -f8,12 data |sort -k2 | uniq -c | column -t
2 Dach Birnen
1 Giebel Birnen
2 Dach Lampen
1 Giebel Lampen