AWK unter Linux verwenden: Text verarbeiten und analysieren

Linux-Werkzeuge orientieren sich häufig an der Unix-Philosophie: Programme sollen möglichst kompakt bleiben, Klartext als Ein- und Ausgabe verwenden und sich modular mit anderen Werkzeugen kombinieren lassen. Aus diesem Ansatz sind leistungsfähige Werkzeuge zur Textverarbeitung wie sed und awk hervorgegangen.

awk ist sowohl eine Programmiersprache als auch ein Werkzeug zur Textverarbeitung. Dadurch eignet es sich besonders gut für strukturierte und zeilenbasierte Daten wie Protokolldateien, Tabellen und einfache Dateien mit Trennzeichen. In diesem Leitfaden lernst du zunächst die grundlegende Muster-und-Aktion-Syntax kennen. Anschließend erfährst du, wie sich awk bei typischen Aufgaben von sed unterscheidet und wie sich Felder filtern, interne Variablen verwenden und Ausgaben formatieren lassen.

Darüber hinaus erfährst du, wie sich mit assoziativen Arrays Werte innerhalb eines einzigen Durchlaufs zählen, gruppieren und zusammenfassen lassen. Außerdem wird gezeigt, wie awk gemeinsam mit anderen Befehlen in Pipelines eingesetzt und für wiederkehrende Automatisierungsaufgaben in Shell-Skripte integriert werden kann. Praktische Beispiele zur Datenanalyse und häufig gestellte Fragen ergänzen den Einstieg in awk.

Die wichtigsten Grundlagen zu AWK

  • Nutze das Muster-und-Aktion-Prinzip von awk, um gezielt bestimmte Zeilen zu erkennen und nur passende Datensätze zu verarbeiten.
  • Behandle Eingabedaten standardmäßig als Felder oder Spalten. Variablen wie $1 und $2 stehen für einzelne Felder, während $0 den vollständigen aktuellen Datensatz enthält.
  • Lege FS und OFS fest, wenn du mit getrennten Daten wie /etc/passwd oder CSV-ähnlichen Dateien arbeitest, damit Ein- und Ausgabe konsistent verarbeitet werden.
  • Verwende BEGIN für einmalige Initialisierungen, beispielsweise zum Definieren von Trennzeichen oder Ausgeben von Überschriften. END eignet sich für abschließende Zusammenfassungen wie Gesamtwerte oder aggregierte Ergebnisse.
  • Mit Variablen wie NR, NF, FILENAME und FNR kannst du datensatzabhängige Logik erstellen, unerwartete Eingaben untersuchen und mehrere Dateien kontrolliert verarbeiten.
  • Assoziative Arrays eignen sich besonders für schnelles Zählen, Gruppieren, Summieren und andere Aggregationen in einem einzigen Durchlauf, ohne zusätzlich sort oder uniq einsetzen zu müssen.
  • Nutze -v, wenn Werte aus der Shell an awk übergeben werden sollen. Dadurch lassen sich Probleme mit Leerzeichen, Anführungszeichen und Sonderzeichen besser vermeiden.
  • awk eignet sich besonders für zeilenorientierte Datenströme und kompakte Auswertungen. Werden die Regeln zur Datenanalyse komplexer, beispielsweise bei CSV-Dateien mit Kommas innerhalb von Anführungszeichen, kann ein spezialisiertes Werkzeug sinnvoller sein.

AWK vs. sed: Welches Werkzeug eignet sich wann?

awk und sed gehören zu den klassischen Unix-Werkzeugen für die Textverarbeitung und werden häufig gemeinsam genannt, weil beide mit Textströmen arbeiten. Sie verfolgen jedoch unterschiedliche Ansätze. Welches Werkzeug geeigneter ist, hängt deshalb von der jeweiligen Aufgabe ab.

Grundsätzlich ist sed ein Stream-Editor, der sich besonders für einfache Änderungen an vollständigen Textzeilen eignet. awk dagegen ist eine Sprache zur Mustererkennung und Datenverarbeitung, die vor allem bei strukturierten oder spaltenorientierten Informationen ihre Stärken ausspielt.

Die wichtigsten Unterschiede zwischen AWK und sed

Merkmal awk sed
Hauptaufgabe Mustererkennung und Datenverarbeitung Bearbeitung von Textströmen und Textänderungen
Datenverarbeitung Feld- und spaltenorientiert Zeilenorientiert
Programmiermöglichkeiten Vollständige Skriptsprache mit Variablen, Schleifen und Arrays Begrenzte Skriptfunktionen mit grundlegenden Befehlen
Besonders geeignet für Strukturierte Informationen wie CSV-Dateien, Logs und Tabellen Einfache Ersetzungen und Textänderungen
Lesbarkeit bei komplexeren Aufgaben Höher Niedriger

Wann sollte sed verwendet werden?

sed eignet sich für einfache Änderungen, die auf einzelne Textzeilen angewendet werden sollen. Besonders praktisch ist das Werkzeug, wenn Inhalte schnell verändert werden müssen, ohne dass dabei die interne Struktur der einzelnen Felder ausgewertet werden muss.

Mit dem folgenden Befehl lässt sich beispielsweise jedes Vorkommen des Wortes „error“ in einer Datei durch „warning“ ersetzen:

sed 's/error/warning/g' file.txt

sed ist insbesondere dann eine gute Wahl, wenn du:

  • Such-und-Ersetzen-Operationen durchführen möchtest.
  • Bestimmte Zeilen entfernen oder einfügen möchtest.
  • Einfache Änderungen auf vollständige Textzeilen anwenden möchtest.

Da sed Text zeilenweise verarbeitet und Felder beziehungsweise Spalten nicht automatisch interpretiert, ist es für strukturierte Datensätze häufig weniger komfortabel.

Wann sollte AWK verwendet werden?

awk ist sinnvoll, wenn strukturierte Daten extrahiert, untersucht oder verändert werden sollen. Im Gegensatz zu sed kennt awk das Konzept einzelner Felder und kann dadurch direkt mit Spalten innerhalb einer Datei arbeiten.

Mit dem folgenden Befehl lassen sich beispielsweise ausschließlich die erste und die dritte Spalte einer Datei ausgeben:

awk '{print $1, $3}' file.txt

awk ist besonders hilfreich, wenn du:

  • Bestimmte Spalten aus tabellarischen Daten auslesen möchtest.
  • Datensätze anhand von Bedingungen filtern möchtest.
  • Berechnungen oder Aggregationen durchführen möchtest.
  • Formatierte Ausgaben oder Berichte erzeugen möchtest.

Da awk Sprachkonstrukte wie Variablen, Bedingungen und Schleifen bereitstellt, lassen sich damit anspruchsvollere Aufgaben der Datenverarbeitung umsetzen als mit sed.

Schnelle Entscheidungshilfe für AWK und sed

Falls du nicht sicher bist, welches der beiden Werkzeuge besser passt, helfen folgende grundlegende Regeln:

  • Nutze sed für einfache, zeilenbasierte Textänderungen, bei denen Felder oder strukturierte Daten keine Rolle spielen.
  • Nutze awk, wenn du mit strukturierten Informationen oder einzelnen Spalten arbeitest oder Bedingungen und Datenverarbeitungslogik benötigst.

Beispiel: AWK und sed im direkten Vergleich

Angenommen, jede Zeile einer Datei enthält mehrere durch Leerzeichen getrennte Felder und du möchtest ausschließlich die erste Spalte ausgeben.

Mit awk lässt sich diese Aufgabe direkt formulieren:

Die gleiche Aufgabe erfordert mit sed einen deutlich umfangreicheren regulären Ausdruck:

sed 's/^\([^ ]*\).*/\1/' file.txt

Beide Befehle liefern dieselben Daten zurück. Die Variante mit awk ist jedoch leichter nachvollziehbar, weil sie die Struktur der Eingabedaten unmittelbar widerspiegelt. Genau darin liegt einer der wesentlichen Unterschiede: awk ist auf Felder ausgerichtet, während sed hauptsächlich Textmuster verarbeitet.

Beide Werkzeuge sind leistungsfähig, wurden jedoch für unterschiedliche Einsatzbereiche entwickelt. sed eignet sich hervorragend für schnelle und einfache Textänderungen. awk bietet dagegen Vorteile bei strukturierten Daten und komplexerer Verarbeitungslogik. Wer diesen Unterschied kennt, kann für eine konkrete Aufgabe leichter das passende Werkzeug auswählen.

Grundlegende AWK-Syntax unter Linux

Der Befehl awk ist auf modernen Linux-Systemen normalerweise standardmäßig vorhanden. Eine zusätzliche Installation ist daher in der Regel nicht erforderlich.

awk eignet sich besonders gut für Textdateien mit vorhersehbarer Struktur. Vor allem tabellarische Informationen lassen sich damit einfach auswerten. Die Eingabe wird dabei zeilenweise gelesen, bis die gesamte Datei verarbeitet wurde.

Standardmäßig verwendet awk Leerraum wie Leerzeichen und Tabulatoren als Feldtrennzeichen. Viele Konfigurationsdateien unter Linux verwenden Strukturen, die sich dadurch direkt verarbeiten lassen.

Die grundlegende Form eines awk-Befehls sieht folgendermaßen aus:

awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parse

Sowohl der Suchausdruck als auch der Aktionsbereich können weggelassen werden. Wird keine Aktion angegeben, besteht die Standardaktion darin, jede passende Zeile auszugeben.

Fehlt dagegen der Suchausdruck, führt awk die angegebene Aktion für jede Eingabezeile aus.

Werden beide Bereiche angegeben, prüft awk den Suchausdruck für die aktuelle Zeile und führt die definierte Aktion aus, sobald eine Übereinstimmung gefunden wird.

In der einfachsten Form lässt sich awk ähnlich wie cat verwenden, um sämtliche Zeilen einer Textdatei auf dem Bildschirm auszugeben.

Erstelle zunächst eine Datei namens favorite_food.txt, die verschiedene Lieblingsgerichte und Namen enthält:

echo "carrot sandy
wasabi luke
sandwich brian
salad ryan
spaghetti jessica" > favorite_food.txt

Nun lässt sich die gesamte Datei mit awk ausgeben:

awk '{print}' favorite_food.txt

Die Ausgabe lautet:

carrot sandy
wasabi luke
sandwich brian
salad ryan
spaghetti jessica

Dieses einfache Beispiel nutzt die Filtermöglichkeiten von awk noch nicht. Um nur Zeilen auszugeben, die den Text „sand“ enthalten, kannst du folgenden Befehl verwenden:

awk '/sand/' favorite_food.txt

Das Ergebnis lautet:

carrot sandy
sandwich brian

awk gibt jetzt nur noch Datensätze aus, in denen die Zeichenfolge „sand“ vorkommt.

Mithilfe regulärer Ausdrücke lässt sich genauer bestimmen, an welcher Stelle eines Textes gesucht werden soll. Soll ausschließlich eine Zeile gefunden werden, die mit „sand“ beginnt, kann der Ausdruck ^sand verwendet werden:

awk '/^sand/' favorite_food.txt

Nun erscheint nur noch die passende Zeile:

Über den Aktionsbereich eines awk-Ausdrucks lässt sich außerdem bestimmen, welcher Teil eines Datensatzes ausgegeben werden soll. Mit folgendem Befehl wird beispielsweise ausschließlich das erste Feld ausgegeben:

awk '/^sand/ {print $1;}' favorite_food.txt

Das Ergebnis ist:

Auf jede durch Leerraum getrennte Spalte kann über eine Variable zugegriffen werden, die ihrer Position entspricht. Das erste Feld wird mit $1 angesprochen, das zweite mit $2. Die komplette aktuelle Zeile steht über $0 zur Verfügung.

Interne AWK-Variablen und erweiterte Syntax

Während awk eine Datei verarbeitet, stellt das Programm verschiedene interne Variablen bereit, die Informationen über die aktuelle Eingabe und den Verarbeitungsstatus enthalten.

Zu den wichtigsten internen Variablen gehören:

  • FILENAME: Enthält den Namen der aktuell verarbeiteten Eingabedatei.
  • FNR: Enthält die Nummer des aktuellen Datensatzes innerhalb der jeweiligen Eingabedatei. Werden mehrere Dateien verarbeitet, beginnt die Zählung für jede Datei erneut.
  • FS: Definiert das Trennzeichen, mit dem ein Eingabedatensatz in einzelne Felder aufgeteilt wird. Standardmäßig wird Leerraum verwendet.
  • NF: Enthält die Anzahl der Felder innerhalb des aktuellen Datensatzes.
  • NR: Enthält die fortlaufende Nummer des aktuellen Datensatzes.
  • OFS: Legt das Trennzeichen zwischen einzelnen Ausgabefeldern fest. Standardmäßig wird Leerraum verwendet.
  • ORS: Definiert das Trennzeichen zwischen ausgegebenen Datensätzen. Standardmäßig handelt es sich um einen Zeilenumbruch.
  • RS: Legt fest, wodurch einzelne Datensätze in der Eingabe voneinander getrennt werden. Standardmäßig wird ein Zeilenumbruch verwendet.

Diese Variablen können an das jeweilige Dateiformat angepasst werden. Häufig werden entsprechende Einstellungen während der Initialisierung vorgenommen.

Mit folgendem Befehl lässt sich beispielsweise jede Zeile gemeinsam mit ihrer Datensatznummer ausgeben:

awk '{print NR, $0}' file.txt

Um auszugeben, aus wie vielen Feldern jede Zeile besteht, kann folgender Befehl verwendet werden:

awk '{print "Fields:", NF}' file.txt

awk unterstützt darüber hinaus optionale BEGIN– und END-Blöcke. Befehle innerhalb von BEGIN werden ausgeführt, bevor die eigentliche Eingabeverarbeitung beginnt. Anweisungen innerhalb von END werden dagegen erst ausgeführt, nachdem sämtliche Datensätze verarbeitet wurden.

Eine erweiterte awk-Syntax kann deshalb folgendermaßen aufgebaut sein:

awk 'BEGIN { action; }
/search/ { action; }
END { action; }' input_file

Die Schlüsselwörter BEGIN und END funktionieren wie besondere Bedingungen. Der erste Block gilt vor der Verarbeitung der Eingabe, der zweite nach Abschluss der Verarbeitung.

Der BEGIN-Block eignet sich deshalb gut, um interne Variablen anzupassen. Die Datei /etc/passwd verwendet beispielsweise Doppelpunkte (:) statt Leerzeichen als Trennzeichen.

Das erste Feld dieser Datei lässt sich mit folgendem Befehl ausgeben:

awk 'BEGIN { FS=":"; }
{ print $1; }' /etc/passwd

Die Ausgabe beginnt mit Einträgen wie diesen:

root
daemon
bin
sys
sync
games
man
. . .

Mit BEGIN und END können außerdem zusätzliche Informationen vor und nach den ausgegebenen Feldern eingefügt werden. Der folgende Befehl formatiert ausgewählte Daten mithilfe von Tabulatoren als übersichtliche Tabelle:

awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
{print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
END { print "---------\nFile Complete" }' /etc/passwd

Die resultierende Ausgabe sieht beispielsweise folgendermaßen aus:

User      UID       GID       Home          Shell
--------------
root      0         0         /root         /bin/bash
daemon    1         1         /usr/sbin     /bin/sh
bin       2         2         /bin          /bin/sh
sys       3         3         /dev          /bin/sh
sync      4         65534     /bin          /bin/sync
. . .
---------
File Complete

Durch diese Funktionen lassen sich verarbeitete Informationen strukturiert und gut lesbar formatieren.

Alle Bereiche der erweiterten Syntax sind optional. Selbst der eigentliche Aktionsbereich kann entfallen, wenn ein anderer Abschnitt definiert wurde. Folgendes Beispiel funktioniert daher ebenfalls:

awk 'BEGIN { print "We can use awk like the echo command"; }'

Dadurch entsteht folgende Ausgabe:

We can use awk like the echo command

Als Nächstes geht es darum, Suchmuster gezielt auf einzelne Felder einer Eingabe anzuwenden.

Felder mit AWK durchsuchen und Bedingungen kombinieren

In einem vorherigen Beispiel wurde in favorite_food.txt eine Zeile ausgewählt, die mit „sand“ beginnt. Das war einfach, weil das Suchmuster am Anfang des vollständigen Datensatzes geprüft wurde.

Mit awk lässt sich jedoch auch kontrollieren, ob ein Muster am Anfang eines bestimmten Feldes und nicht nur am Anfang der gesamten Zeile vorkommt.

Erstelle dafür eine neue Version von favorite_food.txt, bei der vor jedem Gericht und Namen eine Nummer steht:

echo "1 carrot sandy
2 wasabi luke
3 sandwich brian
4 salad ryan
5 spaghetti jessica" > favorite_food.txt

Um alle Einträge mit der Zeichenfolge „sa“ zu finden, könntest du zunächst folgenden Befehl ausprobieren:

awk '/sa/' favorite_food.txt

Dadurch erscheinen sämtliche Zeilen, in denen „sa“ an irgendeiner Stelle vorkommt:

1 carrot sandy
2 wasabi luke
3 sandwich brian
4 salad ryan

Der Ausdruck sucht innerhalb des gesamten Datensatzes nach „sa“. Deshalb werden auch Begriffe wie „wasabi“ gefunden, bei denen die Zeichenfolge in der Wortmitte vorkommt. Ebenso wird „sandy“ berücksichtigt, obwohl sich dieser Wert nicht in der gewünschten Spalte befindet. Wenn ausschließlich Gerichte gesucht werden sollen, die in der zweiten Spalte mit „sa“ beginnen, muss das betreffende Feld Teil der Bedingung sein.

Mit folgendem Befehl wird das Muster ausschließlich am Anfang des zweiten Feldes geprüft:

awk '$2 ~ /^sa/' favorite_food.txt

Damit wird die Suche auf den Beginn der zweiten Spalte beschränkt. Der Ausdruck $2 ~ weist awk an, den regulären Ausdruck gezielt auf das zweite Feld anzuwenden.

Das Ergebnis ist:

3 sandwich brian
4 salad ryan

Eine Übereinstimmung mit einem regulären Ausdruck kann auch umgekehrt werden. Dazu wird vor der Tilde ein Ausrufezeichen eingefügt. Der folgende Ausdruck wählt alle Zeilen aus, bei denen das Gericht nicht mit „sa“ beginnt:

awk '$2 !~ /^sa/' favorite_food.txt

Dadurch ergibt sich folgende Ausgabe:

1 carrot sandy
2 wasabi luke
5 spaghetti jessica

Wenn zusätzlich nur Datensätze ausgewählt werden sollen, deren Nummer kleiner als 5 ist, lassen sich beide Bedingungen miteinander kombinieren:

awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txt

Hier kommt der Operator && zum Einsatz. Damit können mehrere Bedingungen miteinander verknüpft werden, die gleichzeitig erfüllt sein müssen. In diesem Fall wird zusätzlich geprüft, ob der Wert im ersten Feld kleiner als 5 ist.

Die Ausgabe lautet:

1 carrot sandy
2 wasabi luke

Neben der direkten Verarbeitung von Dateien kann awk auch Ausgaben anderer Programme als Eingabe verwenden.

Assoziative Arrays in AWK für Datenaggregation verwenden

Bisher wurde awk hauptsächlich zum Filtern und Ausgeben von Informationen eingesetzt. Eine weitere wichtige Funktion sind assoziative Arrays. Sie ermöglichen es, während der Verarbeitung einer Datei Werte zu speichern.

Im Unterschied zu klassischen Arrays mit numerischen Indizes können assoziative Arrays in awk Zeichenketten als Schlüssel verwenden. Dadurch eignen sie sich besonders gut zum Zählen, Gruppieren und Zusammenfassen von Datensätzen. Beispielsweise kann der Inhalt eines Feldes wie ein Benutzername oder eine Abteilung direkt als Schlüssel dienen.

Vorkommen mit AWK zählen

Eine typische Anwendung für assoziative Arrays besteht darin, zu zählen, wie häufig bestimmte Werte in einer Datei vorkommen. Während jede Zeile gelesen wird, lässt sich ein Zähler für den jeweiligen Schlüssel erhöhen. Die endgültigen Ergebnisse können anschließend innerhalb eines END-Blocks ausgegeben werden.

Betrachte beispielsweise eine Datei namens fruits.txt:

echo "apple
banana
apple
orange
banana
apple" > fruits.txt

Wie oft jede Frucht vorkommt, lässt sich mit folgendem Befehl ermitteln:

awk '{count[$1]++} END {for (item in count) print item, count[item]}' fruits.txt

Die Ausgabe sieht beispielsweise folgendermaßen aus:

Bei diesem Ausdruck gilt:

  • count[$1]++ erhöht einen Zähler für jeden eindeutigen Wert im ersten Feld.
  • $1 wird als Schlüssel des assoziativen Arrays verwendet.
  • Der END-Block gibt die zusammengefassten Ergebnisse aus, nachdem sämtliche Eingabedaten gelesen wurden.

Die Reihenfolge, in der for (item in count) die Schlüssel ausgibt, kann je nach verwendeter awk-Implementierung unterschiedlich sein. Wird eine sortierte Ausgabe benötigt, kann das Ergebnis anschließend an sort weitergeleitet werden.

Daten nach Feldern gruppieren

Mit assoziativen Arrays können zusammengehörige Informationen auch gruppiert werden. Anstelle eines numerischen Zählers lässt sich während der Verarbeitung beispielsweise eine Zeichenkette oder ein anderer Wert pro Schlüssel aufbauen.

Erstelle beispielsweise eine Datei namens employees.txt:

echo "HR Alice
IT Bob
HR Charlie
IT David
Finance Emma" > employees.txt

Die Mitarbeiter lassen sich anschließend nach Abteilungen gruppieren:

awk '{group[$1] = (group[$1] ? group[$1] " " : "") $2} END {for (dept in group) print dept ": " group[dept]}' employees.txt

Eine mögliche Ausgabe lautet:

HR: Alice Charlie
IT: Bob David
Finance: Emma

Dabei gilt:

  • $1, also die Abteilung, wird als Schlüssel verwendet.
  • $2, also der Name des Mitarbeiters, wird an den gespeicherten Wert der entsprechenden Gruppe angehängt.

Der bedingte Ausdruck verhindert, dass vor dem ersten Mitarbeiternamen einer Abteilung ein unnötiges Leerzeichen erscheint.

Werte mit AWK summieren

Assoziative Arrays können außerdem laufende Summen speichern. Dieses Muster eignet sich besonders für Daten, bei denen ein Feld eine Bezeichnung und ein anderes Feld einen numerischen Wert enthält.

Betrachte beispielsweise eine Datei namens sales.txt:

echo "Alice 100
Bob 200
Alice 150
Bob 50" > sales.txt

Der Gesamtwert pro Person lässt sich folgendermaßen berechnen:

awk '{sum[$1] += $2} END {for (name in sum) print name, sum[name]}' sales.txt

Das Ergebnis lautet:

In diesem Beispiel:

  • dient $1 mit dem Namen als Schlüssel.
  • wird der Wert aus $2 zur laufenden Summe des jeweiligen Schlüssels addiert.

Den größten Wert mit AWK ermitteln

Assoziative Arrays können auch genutzt werden, um Maximal- oder Minimalwerte zu bestimmen. Ein typischer Ansatz besteht darin, zunächst Werte pro Schlüssel zu aggregieren und danach das fertige Array zu durchlaufen, um den größten Eintrag zu finden.

awk '{sum[$1] += $2} END {
    for (name in sum) {
        if (top == "" || sum[name] > max) { max = sum[name]; top = name }
    }
    print "Top performer:", top, max
}' sales.txt

Auf diese Weise können Berechnungen und einfache Auswertungen direkt innerhalb von awk durchgeführt werden, ohne dass dafür weitere Werkzeuge erforderlich sind.

Warum assoziative Arrays in AWK wichtig sind

Assoziative Arrays erweitern awk über ein einfaches Filterwerkzeug hinaus und machen es zu einer leichtgewichtigen Lösung für Datenverarbeitung. Während eine Datei gelesen wird, können Informationen gesammelt und am Ende als zusammengefasste Ergebnisse ausgegeben werden.

Mit assoziativen Arrays kannst du:

  • Häufigkeitsverteilungen erstellen.
  • Daten gruppieren und neu organisieren.
  • Aggregierte Werte wie Summen und Anzahlen berechnen.
  • Einfache Datenanalysen direkt auf der Kommandozeile durchführen.

Diese Möglichkeiten sind besonders bei Logdateien, CSV-ähnlichen Dateien und automatisch erzeugten Systemdaten hilfreich.

Ausgaben anderer Programme mit AWK verarbeiten

awk benötigt nicht zwingend einen Dateinamen als Eingabe. Stattdessen kann auch die Ausgabe eines anderen Programms verarbeitet werden. Beispielsweise lässt sich mit awk eine IPv4-Adresse aus der Ausgabe des Befehls ip extrahieren.

Der Befehl ip a zeigt IP-Adressen, Broadcast-Adressen und weitere Informationen über die Netzwerkschnittstellen eines Systems an. Um nur die Angaben für eine Schnittstelle mit dem Namen eth0 anzuzeigen, kann folgender Befehl verwendet werden:

Eine mögliche Ausgabe sieht folgendermaßen aus:

2571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

Mit awk kann gezielt die Zeile mit inet ausgewählt und daraus ausschließlich die IP-Adresse ausgegeben werden:

ip a s eth0 | awk -F '[\/ ]+' '/inet / {print $3}'

Die Option -F weist awk an, Schrägstriche oder Leerzeichen gemäß dem regulären Ausdruck [\/ ]+ als Feldtrennzeichen zu verwenden. Dadurch wird eine Zeile wie inet 172.17.0.11/16 in einzelne Felder unterteilt. Da auch die Leerzeichen am Zeilenanfang berücksichtigt werden, befindet sich die IP-Adresse in diesem Fall im dritten Feld. Aufeinanderfolgende Leerzeichen werden hier als gemeinsames Trennzeichen behandelt.

Die Ausgabe ist:

Nach demselben Prinzip lassen sich mit awk zahlreiche weitere Kommandozeilenausgaben durchsuchen, filtern und analysieren.

AWK in Shell-Skripten und für Automatisierung verwenden

Bisher wurde awk hauptsächlich als einzelner Kommandozeilenbefehl verwendet. Besonders nützlich wird das Werkzeug jedoch, wenn es in Shell-Skripte eingebunden wird, um wiederkehrende Aufgaben der Datenverarbeitung zu automatisieren.

In Kombination mit Bash können kompakte Automatisierungslösungen entstehen, die beispielsweise Logdateien analysieren, Messwerte extrahieren oder Berichte erstellen, ohne zusätzliche Abhängigkeiten einzuführen.

AWK in ein Bash-Skript einbinden

awk-Befehle können wie jeder andere Kommandozeilenbefehl direkt innerhalb eines Shell-Skripts verwendet werden. Das ist praktisch, wenn dieselbe Logik zum Extrahieren von Daten an mehreren Stellen benötigt oder regelmäßig ausgeführt werden soll.

Erstelle beispielsweise ein Skript namens extract_users.sh:

#!/bin/bash

awk -F ":" '{print $1}' /etc/passwd

Anschließend kann das Skript ausführbar gemacht und gestartet werden:

chmod +x extract_users.sh
./extract_users.sh

Das Skript liest sämtliche Benutzernamen aus der Datei /etc/passwd aus und gibt sie aus. Obwohl dieses Beispiel einfach ist, zeigt es, wie sich awk-Logik in wiederverwendbare Skripte integrieren lässt.

Gleichzeitig zeigt es ein häufig verwendetes Muster: -F ":" definiert den Doppelpunkt als Feldtrennzeichen, während print $1 aus jeder Zeile das erste Feld ausgibt.

Variablen aus Bash an AWK übergeben

Über die Option -v können Werte aus einem Shell-Skript an awk übergeben werden. Dadurch lässt sich das Verhalten eines Skripts dynamisch steuern.

#!/bin/bash

threshold=100

awk -v limit="$threshold" '$2 > limit {print $1, $2}' sales.txt

In diesem Beispiel:

  • wird die Bash-Variable threshold innerhalb von awk unter dem Namen limit verfügbar gemacht.
  • gibt awk ausschließlich Datensätze aus, deren zweites Feld den definierten Grenzwert überschreitet.

Auf diese Weise kann die Logik des Shell-Skripts das Verhalten des awk-Programms beeinflussen.

Grundsätzlich ist die Übergabe von Shell-Variablen über -v sicherer und übersichtlicher, als Variablenwerte durch direkte Zeichenkettenverkettung in das awk-Programm einzubauen.

Mehrere Dateien mit AWK verarbeiten

Shell-Skripte werden häufig eingesetzt, um mehrere Dateien nacheinander zu bearbeiten. Schleifen lassen sich dabei mit awk kombinieren, um ganze Dateigruppen zu verarbeiten.

#!/bin/bash

for file in *.log; do
    echo "Processing $file"
    awk '/ERROR/ {print $0}' "$file"
done

Dieses Skript durchläuft sämtliche .log-Dateien im aktuellen Verzeichnis. awk sucht darin nach Zeilen mit „ERROR“ und gibt die passenden Einträge für jede Datei aus.

Wenn Bash verwendet wird und die Schleife nichts ausführen soll, falls keine Dateien auf *.log passen, kann die Option nullglob beispielsweise über shopt -s nullglob aktiviert werden. Dadurch wird das Muster bei fehlenden Treffern zu einer leeren Liste erweitert, anstatt als wörtlicher Text *.log bestehen zu bleiben.

Loganalyse mit AWK automatisieren

Die automatische Analyse von Logdateien gehört zu den typischen praktischen Einsatzmöglichkeiten von awk.

Das folgende Skript zählt beispielsweise, wie viele Fehler innerhalb einer Logdatei vorkommen:

#!/bin/bash

logfile="app.log"

awk '/ERROR/ {count++} END {print "Total errors:", count+0}' "$logfile"

Das Skript durchsucht die Logdatei nach Zeilen mit „ERROR“. Für jeden Treffer wird ein Zähler erhöht. Nach Abschluss der Verarbeitung wird der Gesamtwert innerhalb des END-Blocks ausgegeben.

Durch count+0 wird sichergestellt, dass auch dann 0 ausgegeben wird, wenn keine passende Zeile gefunden wurde.

Dieses Vorgehen lässt sich erweitern, um:

  • Warnmeldungen auszulösen.
  • Tägliche Zusammenfassungen zu erstellen.
  • Ergebnisse an Monitoring-Systeme weiterzugeben.

AWK mit anderen Linux-Befehlen kombinieren

awk wird häufig gemeinsam mit anderen Unix-Werkzeugen innerhalb von Pipelines verwendet, um flexible Arbeitsabläufe auf der Kommandozeile aufzubauen.

grep "404" access.log | awk '{print $1}' | sort | uniq -c

Diese Pipeline filtert Einträge mit dem HTTP-Statuscode 404, liest anschließend die IP-Adresse aus dem ersten Feld aus, sortiert die Adressen und zählt, wie häufig jede einzelne vorkommt.

Obwohl awk häufig mehrere Schritte einer solchen Pipeline selbst übernehmen könnte, können getrennte spezialisierte Werkzeuge ein Skript in manchen Fällen verständlicher und leichter wartbar machen.

Warum AWK für Automatisierung verwenden?

Der Einsatz von awk innerhalb von Shell-Skripten kann dabei helfen:

  • manuelle Datenverarbeitung zu reduzieren.
  • wiederholbare Arbeitsabläufe zu erstellen.
  • Informationen schnell aus systemgenerierten Daten zu extrahieren.
  • für einfache Aufgaben auf umfangreichere Skriptsprachen verzichten zu können.

Da awk auf nahezu allen Unix-ähnlichen Systemen verfügbar ist, lassen sich darauf basierende Skripte meist problemlos in unterschiedlichen Umgebungen einsetzen.

Praxisbeispiele mit AWK: Logs analysieren und Daten extrahieren

Die bisherigen Beispiele zeigen die grundlegende Funktionsweise von awk. Seine eigentliche Stärke zeigt sich jedoch bei konkreten Aufgaben der Datenverarbeitung. Administratoren und Entwickler verwenden awk regelmäßig, um Logdateien auszuwerten, strukturierte Informationen zu extrahieren und direkt auf der Kommandozeile kompakte Berichte zu erzeugen.

Die folgenden Beispiele zeigen typische Situationen, in denen awk eingesetzt werden kann.

Apache-Access-Logs mit AWK analysieren

Webserver-Protokolle gehören zu den häufigsten Quellen strukturierter Textdaten. In vielen standardmäßigen Apache-Konfigurationen werden Zugriffe im sogenannten „combined“-Format gespeichert. Dabei steht die IP-Adresse des Clients am Anfang des Eintrags, während sich der HTTP-Statuscode an einer späteren Stelle befindet.

Ein typischer Eintrag eines Apache-Access-Logs kann beispielsweise so aussehen:

127.0.0.1 - - [10/Oct/2023:13:55:36 +0000] "GET /index.html HTTP/1.1" 200 2326

Um aus jeder Anfrage sowohl die IP-Adresse als auch den HTTP-Statuscode auszulesen, kann folgender Befehl verwendet werden:

awk '{print $1, $9}' access.log

Bei der oben dargestellten Logstruktur enthält $1 die IP-Adresse des Clients, während sich der HTTP-Statuscode in $9 befindet.

Um zu zählen, wie viele Anfragen mit einem 404-Status beantwortet wurden, kann folgender Ausdruck verwendet werden:

awk '$9 == 404 {count++} END {print "404 errors:", count+0}' access.log

Der Ausdruck count+0 sorgt dafür, dass auch dann der Wert 0 erscheint, wenn kein passender Datensatz gefunden wurde.

CSV-Daten mit AWK auslesen

Obwohl awk standardmäßig Leerraum als Feldtrennzeichen verwendet, kann problemlos ein anderes Trennzeichen angegeben werden. Dadurch lassen sich einfache CSV-Dateien direkt verarbeiten.

Betrachte beispielsweise folgende Datei data.csv:

name,age,city
Alice,30,New York
Bob,25,London
Charlie,35,Sydney

Um lediglich Namen und Städte auszugeben, kann folgender Befehl verwendet werden:

awk -F ',' '{print $1, $3}' data.csv

Dieses Verfahren setzt voraus, dass die CSV-Datei keine in Anführungszeichen eingeschlossenen Felder enthält, in denen selbst Kommas vorkommen. Sind solche Werte vorhanden, wird ein Parser benötigt, der das CSV-Format vollständig versteht.

Um ausschließlich Datensätze auszugeben, bei denen das Alter größer als 30 ist, kann folgende Bedingung verwendet werden:

awk -F ',' '$2 > 30 {print $1, $2}' data.csv

Das Beispiel zeigt, dass sich strukturierte Datensätze mit awk durchsuchen und filtern lassen, ohne dafür eine Datenbank einzusetzen.

Linux-Systemdateien mit AWK analysieren

Viele Linux-Systemdateien besitzen ein einheitliches und vorhersehbares Format. Dadurch eignen sie sich gut für die Verarbeitung mit awk.

Mit folgendem Befehl können beispielsweise alle Benutzer aus /etc/passwd aufgelistet werden, deren UID größer als 1000 ist:

awk -F ':' '$3 > 1000 {print $1, $3}' /etc/passwd

Um lediglich zu zählen, wie viele Benutzer diese Bedingung erfüllen, kann folgender Befehl verwendet werden:

awk -F ':' '$3 > 1000 {count++} END {print count+0}' /etc/passwd

Werden keine passenden Benutzerkonten gefunden, wird durch diesen Ausdruck der Wert 0 ausgegeben.

Logdaten mit AWK zusammenfassen

Mehrere Funktionen von awk lassen sich miteinander kombinieren, um kompakte Zusammenfassungen von Logdaten zu erzeugen.

Mit folgendem Befehl kann beispielsweise gezählt werden, wie viele Anfragen von jeder einzelnen IP-Adresse stammen:

awk '{count[$1]++} END {for (ip in count) print ip, count[ip]}' access.log

Dadurch entsteht eine Häufigkeitsverteilung der Anfragen pro Client-Adresse. Die Schleife for (ip in count) garantiert keine bestimmte Reihenfolge der Ergebnisse. Falls eine konstante Sortierung benötigt wird, kann die Ausgabe anschließend an sort weitergeleitet werden.

Durch den Einsatz von awk in solchen Situationen lassen sich Aufgaben automatisieren, die ansonsten umfangreichere Werkzeuge oder manuelle Arbeit erfordern könnten.

Häufig gestellte Fragen zu AWK

1. Was ist der Unterschied zwischen AWK, gawk und mawk?

awk bezeichnet die durch POSIX definierte Sprache und die dazugehörige Kommandozeilenschnittstelle. gawk, kurz für GNU Awk, ist auf vielen Linux-Systemen verbreitet und stellt zusätzliche Funktionen bereit, die über den POSIX-Standard hinausgehen. mawk ist eine weitere Implementierung, die häufig auf hohe Geschwindigkeit und einen geringen Ressourcenverbrauch ausgerichtet ist. Allerdings unterstützt sie möglicherweise nicht alle GNU-spezifischen Erweiterungen von gawk.

2. Wie lege ich in AWK ein eigenes Feldtrennzeichen fest?

Mit der Option -F lässt sich festlegen, wie awk eine Eingabezeile in einzelne Felder aufteilen soll. Der Befehl awk -F':' '{print $1}' /etc/passwd verwendet beispielsweise einen Doppelpunkt als Trennzeichen und gibt aus jeder Zeile das erste Feld mit dem Benutzernamen aus.

3. Was ist der Unterschied zwischen AWK und sed?

sed ist ein Stream-Editor, der sich besonders für zeilenorientierte Veränderungen wie Ersetzungen, Löschungen und Einfügungen eignet. awk ist dagegen eine Sprache zur Mustererkennung, die auf die Verarbeitung einzelner Felder, Bedingungen und einfache Berechnungen ausgelegt ist. Für spaltenbasierte Daten und Berichte ist awk daher häufig geeigneter, während sich sed besonders für unkomplizierte Textänderungen anbietet.

4. Wie kann ich mit AWK die Häufigkeit eines Wortes oder Wertes zählen?

Dafür kann ein assoziatives Array als Zähler verwendet werden. Während die Datei gelesen wird, wird der jeweilige Wert pro Schlüssel erhöht. Anschließend werden die Ergebnisse innerhalb eines END-Blocks ausgegeben. Der Befehl awk '{count[$1]++} END {for (w in count) print w, count[w]}' file.txt zählt beispielsweise alle eindeutigen Werte im ersten Feld.

5. Kann AWK mehrzeilige Datensätze verarbeiten?

Ja. Wird der Datensatztrenner RS mit RS="" auf eine leere Zeichenkette gesetzt, behandelt awk durch Leerzeilen getrennte Blöcke jeweils als einen Datensatz. Das ist hilfreich, wenn Eingaben nicht zeilenweise, sondern in Absätzen oder mehrzeiligen Blöcken strukturiert sind.

6. Wie übergebe ich eine Shell-Variable an einen AWK-Befehl?

Über die Option -v kann ein Shell-Wert einer awk-Variablen zugewiesen werden, bevor die eigentliche Verarbeitung beginnt. Das Beispiel threshold=100; awk -v t="$threshold" '$3 > t {print $0}' file.txt stellt den Shell-Wert innerhalb von awk über die Variable t zur Verfügung.

7. Eignet sich AWK für große Dateien?

Ja. awk verarbeitet Eingaben normalerweise jeweils Datensatz für Datensatz und muss nicht die vollständige Datei in den Arbeitsspeicher laden. Dadurch eignet es sich gut für umfangreiche Datenmengen. Werden Verarbeitungsschritte allerdings sehr komplex oder bestehen aus vielen aufeinanderfolgenden Stufen, kann eine andere Sprache wie Python langfristig leichter zu warten sein. Für schnelles Extrahieren, Filtern und Aggregieren bleibt awk jedoch sehr gut geeignet.

8. Wie speichere und starte ich ein AWK-Programm aus einer Datei?

Ein awk-Programm kann in einer gewöhnlichen Textdatei wie script.awk gespeichert und anschließend mit awk -f script.awk input.txt ausgeführt werden. Besonders bei Programmen mit mehreren Regeln, Funktionen oder Blöcken ist diese Variante übersichtlicher und leichter zu pflegen als ein sehr langer Einzeiler.

Fazit zu AWK unter Linux

Du kennst nun die grundlegenden Möglichkeiten, mit denen sich awk zum Filtern, Formatieren und gezielten Ausgeben von Text aus Dateien und Kommandozeilenausgaben einsetzen lässt. Darüber hinaus bietet awk interne Variablen sowie BEGIN– und END-Blöcke für strukturierte Verarbeitungsabläufe, assoziative Arrays für Aggregationen in einem einzigen Durchlauf und die Möglichkeit, wiederkehrende Aufgaben in Shell-Skripten zu automatisieren. Bei praktischen Datenquellen wie Logdateien und Dateien mit Trennzeichen hilft die Unterscheidung zwischen awk und sed dabei, das passende Werkzeug auszuwählen: awk eignet sich besonders für feldorientierte Datenverarbeitung, während sed seine Stärken bei zeilenorientierten Textänderungen ausspielt.

Für einen tieferen Einstieg in awk steht außerdem ein frei verfügbares Buch der ursprünglichen Entwickler zur Verfügung, das die Sprache ausführlicher behandelt.

Quelle: digitalocean.com

Jetzt 200€ Guthaben sichern

Registrieren Sie sich jetzt in unserer ccloud³ und erhalten Sie 200€ Startguthaben für Ihr Projekt.

Das könnte Sie auch interessieren: