Dieser Beitrag stammt ursprünglich von www.linuxfocus.org
von Javier Palacios Bermejo Über den Autor: Javier schreibt an seiner Doktorarbeit in Astronomie an einer spanischen Universität, wo er ein Workstation Cluster administriert. Die tägliche Arbeit in seinem Fachbereich wird auf Unixmaschinen erledigt. Nach einigen anfänglichen Problemen und Versuchen wurde die Slackware Linux Distribution gewählt. Linux stellte sich als sehr viel besser als andere proprietäre Unixsysteme heraus. Inhalt: |
Zusammenfassung:
Dieser Artikel vermittelt einige Einblicke in die Tricks, die man mit AWK machen kann.
Es ist kein Tutorial, enthält aber viele nützliche Beispiele.
Ursprünglich kam mir die Idee diesen Text zu schreiben, nachdem ich zwei in LinuxFocus veröffentlichte Artikel von Guido Socher gelesen hatte. Einer davon, über find und ähnliche Befehle, zeigte mir, daß ich nicht der einzige war, der die Kommandozeile benutzte. Oft ist es so, daß schöne GUIs einem nicht verraten, wie die Dinge wirklich ablaufen (das ist der Weg, den Windows vor Jahren beschritten hat). Der andere Artikel war über reguläre Ausdrücke. Obwohl reguläre Ausdrücke in diesem Artikel nur oberflächlich erwähnt werden, muß man sie kennen, um das Maximum aus awk und anderen Befehlen wie sed und grep herausholen zu können.
Die Schlüsselfrage ist, ob der awk Befehl wirklich nützlich ist. Die Antwort lautet definitiv ja! Er könnte für einen normalen Benutzer nützlich sein, um Textdateien zu bearbeiten, sie zu reformatieren etc... Für einen Systemadministrator ist AWK ein wirklich sehr wichtiges Hilfsmittel. Z.b /var/yp/Makefile oder schau dir die Initialisierungsscripte an. AWK findet sich überall.
Das erste Mal, daß ich von AWK hörte, ist nichtig genug und lange
genug her, um in Vergessenheit geraten zu sein. Ich hatte einen Kollegen, der mit ein paar
wirklich großen Dateien auf einem kleinen Cray-Rechner arbeiten mußte. Die Handbuchseite
für awk in dem Cray war klein, aber er sagte, daß AWK sehr stark danach
aussähe, wie das, was er bräuchte, obwohl er noch nicht verstanden hatte, wie es zu
benutzen sei.
Eine lange Zeit später, wieder in meinem Leben. Ein Kollege von mir benutzte AWK, um die
erste Spalte aus einer Tabelle einer Datei mit dem folgenden Befehl herauszuziehen:
|
Einfach, nicht wahr? Diese einfache Aufgabe bedarf keiner komplexen Programmierung in C.
Eine einzige Zeile mit AWK tut es.
Wenn wir einmal die Lektion gelernt haben, wie man eine Spalte
herauszieht, dann können wir Dinge tun, wie das Umbenennen von Dateien (append .new to
"files_list"):
|
... und mehr:
Wie du siehst, ist AWK wirklich sehr hilfreich, wenn dieselben Berechnungen sich immer wieder wiederholen ... und außerdem macht es auch viel mehr Spaß, ein AWK Programm zu schreiben, statt zwanzigmal mit Hand dasselbe zu machen.
awk ist eine kleine Programmiersprache, mit einer Syntax, die C in vielen Aspekten sehr ähnlich ist. Es ist eine Interpretersprache und der awk Interpreter bearbeitet die Anweisungen.
Über die Syntax des awk Befehlsinterpreters:
# gawk --help Usage: gawk [POSIX or GNU style options] -f progfile [--] file ... gawk [POSIX or GNU style options] [--] 'program' file ... POSIX options: GNU long options: -f progfile --file=progfile -F fs --field-separator=fs -v var=val --assign=var=val -m[fr] val -W compat --compat -W copyleft --copyleft -W copyright --copyright -W help --help -W lint --lint -W lint-old --lint-old -W posix --posix -W re-interval --re-interval -W source=program-text --source=program-text -W traditional --traditional -W usage --usage -W version --version
Anstatt einfach die Programme in der Kommandozeile in Anführungszeichen (') zu setzen,
können wir, wie du oben sehen kannst, die Anweisungen in eine Datei schreiben und sie mit
der Option -f aufrufen. Mit auf der Kommandozeile definierten Variablen ( durch -v
var=
Awk ist, grob gesprochen, dafür gemacht worden, Tabellen zu verwalten. Dies sind einige Informationen, die innerhalb von Feldern und records gruppiert werden können. Der Vorteil dabei ist, daß die record Definition (und die Felddefinition) flexibel ist.
Awk ist mächtig. Es wurde entworfen, um mit einzeiligen Records zu arbeiten, aber dieser Punkt konnte erweitert werden. Damit du einige dieser Aspekte siehst, schauen wir uns einige illustrative (und wirkliche) Beispiele an.
Drucken von Tabellen auf etwas schönere Art Vielleicht mußtest du schon mal einige ASCII Tabellen ausdrucken, die du von irgendwoher erhalten hast. Zum Beispiel die Hostnamen, die Ethernet- und IP Nummern aus einer Liste. Wenn diese Tabellen wirklich groß sind, wird das Lesen schwierig und wir denken, daß wir diese Liste mit LaTeX oder zumindest in einem besseren Format drucken müssen. Wenn die Tabelle einfach ist, dann ist es nicht zu schwierig:
BEGIN { printf "LaTeX preample" printf "\\begin{tabular}{|c|c|...|c|}" } |
{ printf $1" & " printf $2" & " . . . printf $n" \\\\ " printf "\\hline" } |
END { print "\\end{document}" } |
Sicher, dies ist kein besonderes Programm, aber wir fangen ja auch gerade erst an
...
(die doppelten Backslashes (\) sind notwendig, weil dies das Zeichen ist,
um die shell zu verlassen)
Outputdateien zerlegen (in Scheiben schneiden)
SIMBAD ist eine astronomische Objektdatenbank, die u.a. die Position von Sternen auf den
Himmerlskörpern angibt. Einmal in der Vergangenheit mußte ich Untersuchungen
durchführen, um Charts von einigen Objekten zu zeichnen. Das Interface erlaubte die
Speicherung der Ergebnisse in Textdateien und ich hatte zwei Methoden zur Auswahl: 1)
Erzeugen einer Datei für jedes Objekt, oder 2) es mit der ganzen Inputliste zu füttern
und eine einzige große Output-Log-Datei mit den Abfrageergebnissen zu erhalten. Als ich
mich dazu entschied, die zweite Methode zu wählen, benutzte ich awk, um den großen
Outputlog zu zerlegen (in Scheiben zu schneiden). Natürlich mußte ich dafür einige
Outputcharakteristika benutzen.
|
( $1 == "====>" ) { NomObj = $2 TotObj = $4 if ( TotObj > 0 ) { FS = "|" for ( cont=0 ; cont<TotObj ; cont++ ) { getline print $2 $4 $5 $3 >> NomObj } FS = " " } } |
Tatsächlich wurde der Objektname nicht zurückgegeben und alles war ein bißchen komplizierter, aber dies soll nur ein illustratives Beispiel sein. |
Spielen mit der Mailspool
BEGIN { BEGIN_MSG = "From" BEGIN_BDY = "Precedence:" MAIN_KEY = "Subject:" VALIDATION = "[MONTH REPORT]" HEAD = "NO"; BODY = "NO"; PRINT="NO" OUT_FILE = "Month_Reports" } { if ( $1 == BEGIN_MSG ) { HEAD = "YES"; BODY = "NO"; PRINT="NO" } if ( $1 == MAIN_KEY ) { if ( $2 == VALIDATION ) { PRINT = "YES" $1 = ""; $2 = "" print "\n\n"$0"\n" > OUT_FILE } } if ( $1 == BEGIN_BDY ) { getline if ( $0 == "" ) { HEAD = "NO"; BODY = "YES" } else { HEAD = "NO"; BODY = "NO"; PRINT="NO" } } if ( BODY == "YES" && PRINT == "YES" ) { print $0 >> OUT_FILE } } |
Vielleicht verwalten wir eine Mailingliste und von Zeit zu Zeit
werden einige spezielle Nachrichten (z.B. monatliche Berichte) in einem speziellen Format
(subject als '[Monatsbericht] Monat , Abteilung') an die Liste geschickt. Plötzlich, am
Ende des Jahres entscheiden wir uns all diese Nachrichten zusammen, getrennt von den
anderen, zu speichern. Dies kann durch Bearbeitung der mail spool mit dem awk Programm links erreicht werden. Um jeden Bericht, der in eine individuelle Datei geschrieben wurde, zu bekommen, müssen wir drei Zeilen Extra-Code schreiben. |
Bemerkung: Bei diesem Beispiel wird angenommen, daß die mail spool strukturiert ist, wie ich denke, daß sie es ist. Dieses Programm arbeitet für meine Post. |
Ich habe awk für viele andere Aufgaben benutzt (automatisches
Generieren von Webseiten mit Informationen von einfachen Datenbanken) und ich weiß genug
über awk Programmierung, um sicher zu sein, daß man damit eine Menge tun kann.
Laß deinem Vorstellungsvermögen freien Lauf.
Bis jetzt haben fast alle Beispiele alle Inputdateizeilen bearbeiten. Aber, wie auch
die Handbuchseite bemerkt, ist es möglich, nur einige Inputzeilen zu bearbeiten. Man muß
nur die Gruppe von Befehlen mit der Bedingung versehen, die die Zeile erfüllen soll. Die
passende Bedingung könnte sehr flexibel sein, variierend von einem einfachen regulären
Ausdruck zu einer Überprüfung des Inhalts einiger Felder mit der Möglichkeit von
Gruppenbedingungen mit den geeigneten logischen Operatoren.
Wie jede andere Programmiersprache implementiert auch awk alle notwendigen Kontollstrukturen sowie einen Satz von Operatoren und vordefinierten Funktionen, um mit Zahlen und Zeichenketten zu arbeiten.
Es ist aber natürlich möglich, benutzerdefinierte Funktionen mit dem Schlüsselwort function
zu definieren. Außer den gewöhnlichen Skalarvariablen ist awk auch in der Lage, Felder
verschiedener Größe zu handhaben.
Wie es in jeder Programmiersprache vorkommt, gibt es einige oft benutzte Funktionen und
es ist unbequem, Codestücke immer mit cut & paste rüberzukopieren. Das ist der
Grund, warum Bibliotheken existieren. Mit der GNU Version von awk ist es
möglich, sie in ein awk Programm einzubinden. Dies ist jedoch ein Ausblick zu
Dingen, die möglich sind, aber außerhalb der Reichweite dieses Artikels liegen.
Sicherlich ist awk vielleicht nicht so mächtig wie andere Werkzeuge, die zu ähnlichen Zwecken entworfen wurden. Aber es hat den großen Vorteil, daß es möglich ist, in wirklich kurzer Zeit kleine Programme zu schreiben, die voll auf die eigenen Bedürfnisse zugeschnitten sind.
AWK ist sehr passend für die Zwecke, für die es entworfen wurde: Einlesen von Daten Zeile für Zeile und auf den Zeichenketten und Mustern dieser Zeilen operieren.
Dateien wie /etc/password stellen sich als ideal für das Reformatieren und Bearbeiten mit AWK heraus. AWK ist unschätzbar für solche Aufgaben.
Natürlich ist AWK nicht allein. Perl ist ein starker Konkurrent, aber es ist trotzdem
hilfreich, einige AWK Tricks zu kennen.
Diese Art von einfachen Grundfunktionen ist nicht gut dokumentiert, aber du findest etwas, wenn du dich umschaust.
Normalerweise erwähnen alle Bücher über Unix diesen Befehl, aber nur einige
behandeln ihn ausführlich. Das beste, was man machen kann, ist, in jedem Buch, das einem
in die Hände fällt, danach zu suchen. Man weiß nie, wo man unerwartet nützliche
Informationen finden kann.
Dem LinuxFocus-Team schreiben © Javier Palacios Bermejo LinuxFocus 1999 |
Authoren und Übersetzer:
|
1999-10-16, generated by lfparser version 0.7