AWK: Textfilterung per Skript |
|||||||||||||||
* Einführung * Installation * Paketmanager * Grundlagen * Shells * Entwicklung * KDE * Skriptsprachen * AWK * PHP * Perl * Apache * Veranstaltungen * Schulungen * Bücher * Netzwerk * OpenOffice * OpenSource * Samba | |||||||||||||||
AWK![]() Home AWK-Skripte kompilieren Einführung Mit freundlicher Unterstützung von: Linux-Kurse und Seminare ![]() Veranstalter des Linux-Tag am Bodensee 2007 und 2008 Kontakt Haftung Impressum Problem Hilfe Startseite |
Allgemeine Arbeitsweise des AWKDie allgemeine Arbeitsweise des AWK verdeutlicht das folgende Diagramm: ![]() Für jede Zeile der Eingabedatei werden alle Anweisungen des
AWK-Skriptes ausgeführt (mit Ausnahme der unter BEGIN und END
stehenden Anweisungen, die wir jedoch erst später behandeln)
Das einfachste "sinnvolle" AWK-Skript ist { print } Der Aufruf dieses Skriptes mit einer Textdatei, also zum Beispiel awk '{ print }' interessantes.txt gibt jede Zeile der Datei interessantes.txt aus. Damit ist dieser Aufruf identisch mit dem Shell-Skript "cat" Reguläre AusdrückeReguläre Ausdrücke sind für die meisten Linux/Unix Tools und Skript-Sprachen essentiell, deshalb sollte sich jeder, der ernsthaft mit Linux arbeiten will, die Mühe machen, sie zu verstehen. Auch wenn einem am Anfang ein Ausdruck wie^[0-9]+\.[0-9][0-9] *EUR recht kryptisch vorkommen mag, so kann man es bald mit ein wenig Übung wie eine Überschrift in der Tageszeit lesen. Damit die folgenden Beispiele nicht allzu trocken sind, werden wir Heinrich Heines "Lorelei" als zu filternde Beispieldatei wenn möglich verwenden:
Speichern Sie das Gedicht bitte als heine.txt, wenn Sie die folgenden Beispiele nachvollziehen wollen. Ein regulärer Ausdruck in Linux (ebenso wie in Unix) beschreibt ein Textmuster (text pattern), welches eine Folge von Zeichen definiert. Ein recht einfaches aber dennoch mächtiges Tool, welches reguläre Ausdrücke benutzt, ist das Kommando grep, bzw. fgrep und egrep. grep "Schiff" heine.txtliefert als Ausgabe alle Zeilen, die das Wort "Schiff" enthalten: Den Schiffer im kleinen SchiffeStellen wir uns nun vor, dass wir eine Zeile suchen, von der wir wissen, dass das Wort oder "kämmt" drin vorkommt und außerdem das Wort "Kamme". Diese Aufgabe kann man elegant mit einem einfachen regulären Ausdruck lösen. Zunächst muss man wissen, dass eine Punkt "." innerhalb eines regulären Ausdrucks für ein beliebiges Zeichen steht. Ein Stern "*" heißt, dass das vor ihm stehende Zeichen beliebig oft vorkommen kann (also auch überhaupt nicht!). Der Ausdruck ".*" passt also auf eine beliegige Zeichenkette. grep "kämmt.*Kamme" heine.txtliefert die gewünschte Zeile: Sie kämmt es mit goldenem KammeMöchten wir nun alle Zeilen herausfiltern, in denen entweder das Wort "Jungfrau" oder das Wort "Lorelei" vorkommt, so lässt sich dies mit grep nicht mehr elegant bewerkstellen. Um diese Aufgabe zu lösen benötigen wir egrep, was jedoch im Prinzip das gleiche ist, als würde man grep mit der Option "-E" aufrufen. Egrep kann erweiterte reguläre Ausdrücke verarbeiten. egrep "Jungfrau|Lorelei" heine.txtliefert die beiden Zeilen, die jeweils eines der beiden Suchwörter enthalten: Die schönste Jungfrau sitzetSonderzeichen in regulären Ausdrücken und ihre Bedeutung:
VerzweigungenVerzweigungen sind in Awk analog zu anderen Programmiersprachen, wie z.B. C, gelöst, d.h. sie sind wie folgt realisiert:
SchleifenAuch die Schleifen sind in Awk analog zu anderen Programmiersprachen designed.WhileDie while-Schleife gibt es in zwei Varianten, zum einen als annehmende (Schleife wird mindestens einmal durchlaufen) und als abweisende (Schleife wird nur bearbeitet, wenn die Precondition erfüllt ist) Schleifeannnehmend:
abweisend:
ForDer for-Schleife müssen drei Argumente übergeben werden:
Records und FieldsAwk arbeitet unter der Annahme, dass die Eingabe strukturiert ist. Im einfachsten Fall kann dies zum Beispiel bedeuten, dass jede Eingabezeile einem Rekord entspricht und die einzelnen Wörter (Fields oder Felder) durch Tabulatoren oder Leerzeichen (Blanks) getrennt sind. Die Zeichen, die die Felder voneinander trennen werden auch häufig als Delimiter bezeichnet.Hat man z.B. eine Datei mit folgendem Inhalt (Name und Telefonnummer):
Nehmen wir an, dass diese Datei unter dem namen phone.txt gespeichert ist.
Obiges Kommando-Zeilen-Skript liefert z.B. folgende Ausgabe:
$0 ist ein Bezeichner für die ganze Zeile. Das folgende Skript "echoe"t deshalb lediglich die Datei:
ArraysDie Namen von AWK-Arrays unterliegen der gleichen Syntax wie andere Variable. Auch wenn die Arrays in AWK denjenigen in C sehr ähnlich sind, gibt es wesentliche Unterschiede:
Im folgenden Beispiel werden verschiedene Temperaturen dem Array "Temperatur" zugewiesen.
Will man sich das gesamte Array ausgeben lassen, so geht dies wie folgt:
Worthäufigkeiten in einem TextDas folgende Skript ermittelt die Worthäufigkeiten in einer Datei. Jedes Wertepaar einer Ausgabezeile entspricht: (Länge der Worte, Häufigkeit) Anmerkung: NF ist eine vordefinierte Variable, die die Anzahl der Felder pro Zeile angibt. Jedes Feld (field) ist standardmäßig durch Leerzeichen, Zeilenanfang oder Zeilenende begrenzt. Man kann den Feld-Seperator durch folgende Anweisung von einem Leerzeichen z.B. zu einem Komma ändern: FS = ","
PraxisbeispieleJede zweite Zeile, gerade FelderIn der Praxis kommt es häufig vor, dass man die geraden oder ungeraden Zeilen einer Datei ausgeben bzw. zur Weiterverarbeitung ansprechen will.Dazu genügt ein erstaunlich kurzes Skript: Für die Ausgabe der Zielennummern mit geradem Index (Achtung: Zählung beginnt bei 0): awk 'NR%2' DateinameFür die Ausgabe der Zielennummern mit ungeradem Index: awk '(NR+1)%2' DateinameEinem Anfänger mit AWK fällt wohl folgende auch funktionierende aber weniger elegante Lösung zuerst ein: awk 'NR % 2 == 0 { print }' FILENAMEWie sieht es aber aus, wenn man nur die geraden Feldelemente einer Zeile ausgeben will. Das folgende Skript löst dieses Problem. NF ist eine Systemvariable, die die Anzahl der Feldelemente enthält. Man beachte auch, dass die Zählung der Feldelemente mit 1 beginnt, also $1, $2, $3, ..:
|