EMZETT.
Login

Kurz: Die eigentliche Stärke von AWK: Muster, die auf jede Zeile angewendet werden. Im Kurs erzeugen wir die Daten direkt im Beispiel (per printf und Pipe), wie man es auch in einem Shell-Skript tun würde.

Teil des Kurses AWK

Kapitel 4 von 8 im Kurs AWK. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Eingabe zeilenweise verarbeiten

Die eigentliche Stärke von AWK: Muster, die auf jede Zeile angewendet werden. Im Kurs erzeugen wir die Daten direkt im Beispiel (per printf und Pipe), wie man es auch in einem Shell-Skript tun würde.

printf 'Mia 17 Berlin\nTom 25 Hamburg\nZoe 31 Koeln\nBen 12 Berlin\n' | awk '
    NR == 1 { print "Erste Zeile:", $0 }
    $2 > 20 { print $1, "ist über 20" }
    /Berlin/ { berlin++ }
    END { print NR, "Zeilen,", berlin, "aus Berlin" }
'

Ausgabe:

Erste Zeile: Mia 17 Berlin
Tom ist über 20
Zoe ist über 20
4 Zeilen, 2 aus Berlin

Mehrere Muster pro Programm sind erlaubt; trifft eine Zeile mehrere, laufen alle Aktionen nacheinander.

Spalten, Trenner und Formatierung

printf 'name;preis;menge\nApfel;1.20;10\nBirne;0.80;25\nKiwi;2.50;4\n' | awk -F';' '
    BEGIN { OFS = " | " }
    NR == 1 { print $1, $2, $3, "summe"; next }
    {
        summe = $2 * $3
        gesamt += summe
        printf "%-6s %6.2f %4d %8.2f\n", $1, $2, $3, summe
    }
    END { printf "Gesamt: %.2f\n", gesamt }
'

Ausgabe:

name | preis | menge | summe
Apfel    1.20   10    12.00
Birne    0.80   25    20.00
Kiwi     2.50    4    10.00
Gesamt: 42.00

next springt zur nächsten Zeile. Mit -F legst du den Feldtrenner fest, auch als Regex (-F'[,;]').

Muster-Bereiche und Bedingungen

printf 'a\nSTART\nb\nc\nEND\nd\n' | awk '/START/,/END/ { print NR ": " $0 }'
echo ---
printf '1\n2\n3\n4\n5\n6\n' | awk 'NR % 2 == 0'
echo ---
printf 'x 5\ny 15\nz 25\n' | awk '$2 >= 10 && $2 < 20'
echo ---
printf 'a b c\n\nd e\n' | awk 'NF { print NF ": " $0 }'
echo ---
printf 'eins\nzwei\ndrei\n' | awk 'END { print $0, NR }'

Ausgabe:

2: START
3: b
4: c
5: END
---
2
4
6
---
y 15
---
3: a b c
2: d e
---
drei 3

Mehrere Dateien und FILENAME

printf 'a\nb\n' > /tmp/awk-eins.txt
printf 'c\nd\ne\n' > /tmp/awk-zwei.txt
awk '{ print FILENAME ":" FNR ":" NR ": " $0 }' /tmp/awk-eins.txt /tmp/awk-zwei.txt
awk 'FNR == 1 { print "== " FILENAME " ==" } END { print NR " Zeilen insgesamt" }' /tmp/awk-eins.txt /tmp/awk-zwei.txt
rm /tmp/awk-eins.txt /tmp/awk-zwei.txt

Ausgabe:

/tmp/awk-eins.txt:1:1: a
/tmp/awk-eins.txt:2:2: b
/tmp/awk-zwei.txt:1:3: c
/tmp/awk-zwei.txt:2:4: d
/tmp/awk-zwei.txt:3:5: e
== /tmp/awk-eins.txt ==
== /tmp/awk-zwei.txt ==
5 Zeilen insgesamt

Ausgabe umleiten und Pipes

printf 'b 2\na 1\nc 3\n' | awk '{ print $1, $2 | "sort" } END { close("sort"); print "fertig" }'
printf '1\n2\n3\n' | awk '{ s += $1 } END { print "Summe:", s, "Mittel:", s / NR }'
printf 'x\n' | awk '{ print "auf stderr" > "/dev/stderr"; print "auf stdout" }' 2>/dev/null
printf 'ein Satz hier\n' | awk '{ for (i = NF; i >= 1; i--) printf "%s%s", $i, (i > 1 ? " " : "\n") }'

Ausgabe:

a 1
b 2
c 3
fertig
Summe: 6 Mittel: 2
auf stdout
hier Satz ein

Merke

  • Muster wählen Zeilen aus (Regex, Vergleich, Bereich a,b), Aktionen verarbeiten sie
  • -F setzt den Feldtrenner, OFS den Ausgabe-Trenner; next überspringt eine Zeile
  • NR zählt über alle Dateien, FNR pro Datei; FILENAME nennt die Datei
  • Ausgabe lässt sich mit > und | umleiten (close() nicht vergessen)

Übungsaufgabe

Summiere die dritte Spalte einer CSV-Datei, gruppiert nach der ersten Spalte.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Arrays und Zeichenketten

Weiter: Fortgeschrittene Techniken

Alle Kapitel: AWK im Überblick