|
|
(29 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
Zeile 1: |
Zeile 1: |
| {{DISPLAYTITLE:gawk}} | | {{DISPLAYTITLE:Kategorie:gawk}} |
| | [[Kategorie:Linux/Befehl]] |
| | [[Kategorie:Bash/Scripting]] |
| | [[Kategorie:Regular Expression]] |
|
| |
|
| '''awk''' ist eine Programmiersprache zur Bearbeitung und Auswertung beliebiger Textdaten
| | {{DEFAULTSORT:Kategorie:gawk}} |
| | |
| = Einführung =
| |
| * Man kann awk als Weiterentwicklung oder Ergänzung des Streameditors sed betrachten, sie teilen gewisse syntaktische Elemente wie etwa reguläre Ausdrücke.
| |
| * Im Unterschied zu sed stehen in awk aber C-ähnliche Strukturen (if .. then .. else, verschiedene Schleifen, C-Formate …) zur Verfügung, die einen wesentlich leichteren Programmaufbau erlauben.
| |
| * In der Minimalanwendung wird awk in Shell-Skripten eingesetzt, um als Filter zum Beispiel Dateinamen zusammenzusetzen.
| |
| * Mit ausführlicheren Programmen gelingt es, Textdateien zu bearbeiten, umzuformen oder auszuwerten.
| |
| * Dazu stehen neben den üblichen Stringfunktionen aber auch mathematische Grund-Funktionen zur Verfügung.
| |
| * Der Name "awk" ist aus den Anfangsbuchstaben der Nachnamen ihrer drei Autoren Alfred V. Aho, Peter J. Weinberger und Brian W. Kernighan zusammengesetzt.
| |
| * Der freie Awk-Abkömmling der GNU-Gemeinde gawk zeigt sich zu POSIX konform und wird in den folgenden Abschnitten behandelt.
| |
| | |
| | |
| * '''AWK''' ergibt sich auf den Initialen seiner Erfinder * Alfred V. '''A'''ho, Peter J. '''W'''einberger, Brian '''K'''ernighan
| |
| * und erweiterte erstmals 1978 den Werkzeugfundus von Unix Version 7. Jener Kernighan prägte übrigens gemeinsam mit Dennies Ritchie maßgeblich die Entstehung der Programmiersprache C
| |
| * wen wundern da noch die Analogien beider Sprachen?
| |
| * 1987 wartete Awk mit einer komplett überarbeiteten Fassung auf.
| |
| * Wesentliche Bestandteile fanden im später definierten POSIX-Standard Einzug.
| |
| | |
| * Der wesentliche Unterschied von Awk zu anderen Programmiersprachen wie den Skriptsprachen der UNIX Shells, C oder Tcl/Tk besteht in der ''datenorientierten Arbeitsweise'', während die typischen Vertreter prozeduraler Programmiersprachen ''funktionsorientiert'' wirken.
| |
| | |
| * Ein awk-Programm wirkt implizit wie eine endlose Schleife, die fortwährend durchlaufen wird, bis keine Daten mehr in der Eingabe stehen oder das Programm »bewusst« verlassen wird, d. h. der Steuerfluss ist maßgeblich durch die Daten gegeben.
| |
| | |
| * In den meisten anderen Programmiersprachen wird das Hauptprogramm aber einmalig initiiert und Funktionen beeinflussen den Fortschritt der Berechnung.
| |
| | |
| * Awk ähnelt somit eher dem Streameditor (sed); er vermag allerdings bedeutend mehr als die »bloße« Modifikation von Textdateien, denn Awk kennt Variablen, Vergleiche, Funktionen, Schleifen u.a.m. und ermöglicht eine Interaktion mit dem System.
| |
| | |
| * Da in Linux-Installationen nahezu ausschließlich die GNU-Implementierung des Werkzeugs vorzufinden ist, werden wir nachfolgend immer die Bezeichnung »awk« verwenden und meinen damit eigentlich »gawk«.
| |
| | |
| * Zeigen die Beispiele auf Ihrem System abweichende oder fehlerhafte Reaktionen, überprüfen Sie, ob »awk« in ihrem System ein Link auf »gawk« ist.
| |
| | |
| = Reguläre Ausdrücke in Mustern =
| |
| siehe [[Gawk:Reguläre Ausdrücke in Mustern]]
| |
| | |
| = Datenfelder und Variablen =
| |
| siehe [[gawk:Datenfelder und Variablen]]
| |
| | |
| = Operatoren =
| |
| siehe [[Gawk:Operatoren]]
| |
| | |
| = Kontrollstrukturen =
| |
| siehe [[gawk:Kontrollstrukturen]]
| |
| | |
| = Ein- und Ausgabe =
| |
| siehe [[gawk:Ein- und Ausgabe]]
| |
| | |
| = Arrays =
| |
| [[gawk:Arrays]]
| |
| | |
| = Eingebaute Funktionen =
| |
| * Der bevorzugte Einsatzbereich von Awk ist die automatische Generierung von Reports und Statistiken.
| |
| * So existieren zahlreiche eingebaute Funktionen, die Awk zur Auswertung von Daten jeglicher Art prädestinieren.
| |
| * Eine Funktion ist gekennzeichnet durch einen Namen und der Liste der Argumente, die dem Namen, eingeschlossen in runde Klammern, folgen.
| |
| * Es ist bei einigen Funktionen zulässig, weniger Argumente anzugeben, als die Funktion eigentlich bedingt; welche voreingestellten Werte dann Awk einsetzt, unterscheidet sich von Funktion zu Funktion.
| |
| * Stets ein Syntaxfehler hingegen ist, mehr Argumente einer Funktion mitzugeben, als bei ihrer Definition vereinbart wurden.
| |
| * Finden Ausdrücke als Argumente Verwendung, so werden diese vor der Übergabe an die Funktion ausgewertet, d.h.
| |
| * bspw Funktion(i++); liefert (zumeist) ein anderes Ergebnis als Funktion(i); i++;.
| |
| * Allerdings ist die Reihenfolge der Auswertung der Argumente unspezifiziert; eine Funktion wie atan2(x++, x-1); kann in unterschiedlichen Implementierungen zur unterschiedlichen Ergebnissen führen.
| |
| == Mathematische Funktionen ==
| |
| Zur numerischen Berechnung stellt Awk folgende Funktionen zur Verfügung:
| |
| {|class="wikitable" | |
| |-
| |
| | |
| |
| | | Liefert den Arcus-Tangens (in rad) von x/y
| |
| |-
| |
| | | <tt>'''cos(x) '''</tt>
| |
| | | Liefert den Consinus von x
| |
| |-
| |
| | | <tt>'''exp(x) '''</tt>
| |
| | | Berechnet ex
| |
| |-
| |
| | | <tt>'''int(x) '''</tt>
| |
| | | Ganzzahliger Wert von x, wobei »in Richtung 0« gerundet wird
| |
| |-
| |
| | | <tt>'''log(x) '''</tt>
| |
| | | Liefert den natürlichen Logarithmus von x
| |
| |-
| |
| | | <tt>'''rand() '''</tt>
| |
| | | Liefert eine Zufallszahl im Bereich von [0,1]
| |
| |-
| |
| | | <tt>'''sin(x) '''</tt>
| |
| | | Liefert den Sinus von x
| |
| |-
| |
| | | <tt>'''sqrt(x)'''</tt>
| |
| | | Liefert die Quadratwurzel von x
| |
| |-
| |
| | | <tt>'''srand([x]) '''</tt>
| |
| | | Setzt den Startwert für die Zufallszahlen-Generierung [mittels rand()].
| |
| * Geliefert wird der »alte« Startwert
| |
| |-
| |
| |}
| |
| | |
| * Die Funktion zur Erzeugung von Zufallszahl liefert nicht wirklich zufällige Zahlen, sondern eine Folge relativ gleichverteilter Zahlen im Intervall [0,1].
| |
| * Mit jedem Start eines Awk-Programms wird somit stets dieselbe Folge von Zufallszahlen generiert.
| |
| * Genügt dieser »Zufall« nicht aus, muss mit '''srand() '''ein neuer Bezugspunkt für '''rand() '''gesetzt werden. '''srand() '''ohne Argument erzeugt diesen Startwert aus aktuellem Datum und Uhrzeit, womit '''rand() '''tatsächlich den Eindruck zufälliger Werte erweckt.
| |
| * Einige Anwendungsbeispiele sollen die Verwendung der Funktionen demonstrieren:
| |
| # Berechnung von π
| |
| $ '''awk 'BEGIN { printf("π=%.50f\n", 4*atan2(1,1)); }''''
| |
| π=3.14159265358979311599796346854418516159057617187500
| |
| | |
| # Ganzzahliger Anteil eines Wertes
| |
| $ '''awk 'BEGIN { print int(-7), int(-7.5), int (7), int(7.5)}''''
| |
| -7 -7 7 7
| |
| | |
| # Der natürliche Logarithmus von e1
| |
| $ '''awk 'BEGIN { print log(exp(1))}''''
| |
| 1
| |
| | |
| '''Anmerkung'''
| |
| * Das Beispiel der Berechnung von π zeigt die Genauigkeitsschranke der verwendeten Awk-Implementierung; ab der 48. Nachkommastelle ist Schluss.
| |
| * Allerdings genügt die interne Darstellung, um bei Umkehrrechnungen auf den Ausgangswert zu kommen (log(exp(1))).
| |
| | |
| == Zeichenkettenfunktionen ==
| |
| * Die nachfolgend diskutierten Funktionen durchsuchen oder manipulieren Zeichenketten.
| |
| {|class="wikitable"
| |
| |-
| |
| | | <tt>'''gsub(Regex,Ersatz,[String])'''</tt>
| |
| | | Jedes Vorkommen des Regulären Ausdrucks Regex in String wird durch Ersatz ersetzt.
| |
| * Wird String nicht angegeben, wird $0 bearbeitet.
| |
| * Rückgabewert ist die Anzahl der Ersetzungen.
| |
| |-
| |
| | | <tt>'''index(Suchstring,Muster)'''</tt>
| |
| | | Liefert die Position, an der Muster in Suchstring erstmals vorkommt oder 0
| |
| |-
| |
| | | <tt>'''length([String])'''</tt>
| |
| | | Liefert die Länge von String; fehlt String, wird die länge von $0 zurückgegeben
| |
| |-
| |
| | | <tt>'''match(String,Regex)'''</tt>
| |
| | | Liefert die Position des ersten Auftretens des Regulären Ausdrucks Regex in String; setzt RSTART und RLENGTH
| |
| |-
| |
| | | <tt>'''split(String,Feld,[Seperator])'''</tt>
| |
| | | Zerlegt String in einzelne Elemente und legt diese in Feld ab.
| |
| * Als Trennzeichen dient Seperator oder FS, falls dieser nicht angegeben wurde.
| |
| * Rückgabewert ist die Anzahl der Elemente.
| |
| |-
| |
| | | <tt>'''sprintf("Format",Ausdruck)'''</tt>
| |
| | | Anwendung wie '''printf, '''anstatt einer Ausgabe gibt die Funktion die resultierende Zeichenkette zurück
| |
| |-
| |
| | | <tt>'''sub(Regex,Ersatz,[String])'''</tt>
| |
| | | Arbeitsweise wie '''gsub, '''es wird aber nur das erste Muster ersetzt
| |
| |-
| |
| | | <tt>'''substr(string,p,[l])'''</tt>
| |
| | | Gibt eine Teilzeichenkette von string der Länge l, beginnend an Position p zurück
| |
| |-
| |
| | | <tt>'''tolower(string)'''</tt>
| |
| | | Wandelt Groß- in Kleinbuchstaben um, Rückgabewert ist die neue Zeichenkette
| |
| |-
| |
| | | <tt>'''toupper(string)'''</tt>
| |
| | | Wandelt Klein- in Großbuchstaben um, Rückgabewert ist die neue Zeichenkette
| |
| |-
| |
| |}
| |
| == Ermitteln der längsten Zeile einer Datei ==
| |
| $ '''expand default.htm | awk '{x = (x < length()) ? length():x;} END {print x}''''
| |
| 566
| |
| == In welcher Zeile und welcher Position erscheint ein Muster ==
| |
| $ '''awk '/Partitionstabelle/ {print "Zeile:", NR, "Spalte", index($0,"Partitionstabelle")}'''' Linuxfibel/installbefore.htm
| |
| Zeile: 804 Spalte 14
| |
| Zeile: 818 Spalte 81
| |
| Zeile: 837 Spalte 57
| |
| Zeile: 838 Spalte 41
| |
| Zeile: 843 Spalte 41
| |
| Zeile: 972 Spalte 12
| |
| | |
| == Sonstige Funktionen ==
| |
| {|class="wikitable"
| |
| |-
| |
| | | <tt>'''close(Datei) '''</tt>
| |
| | | Schließt eine zuvor zum Lesen oder Schreiben geöffnete Datei oder die Pipe, die als Eingabe oder Ausgabe eines Kommandos diente (dann muss anstatt eines Dateinamens der Kommandoaufruf angegeben werden)
| |
| |-
| |
| | | <tt>'''fflush(Datei)'''</tt>
| |
| | | Leert unverzüglich den Puffer einer »gepufferten« Ausgabe.
| |
| * D.h.
| |
| * veränderte Daten einer Datei werden sofort zurückgeschrieben oder die in eine Pipe geleitete Ausgabe eines Kommandos wird sofort aus dieser entnommen.
| |
| * Bei fehlendem Argument entleert Gawk die Standardausgabe; bei Angabe der leeren Zeichenkette ("") werden die Puffer sämtlicher offener Ausgabedateien und Pips entleert.
| |
| |-
| |
| | | <tt>'''system(Kommando) '''</tt>
| |
| | | Gestattet die Ausführung von beliebigen Kommandos.
| |
| * Nach Ende eines solchen wird im Awk-Programm fortgefahren.
| |
| * system liefert den Status des letzten gestarteten Kommandos zurück.
| |
| |-
| |
| | | <tt>'''systime()'''</tt>
| |
| | | Liefert die Systemzeit in Sekunden (seit 1.1.1970)
| |
| |-
| |
| | | <tt>'''strftime([Format [,Zeitstempel]])'''</tt>
| |
| | | Liefert eine Datumszeichenkette.
| |
| * Ohne Zeitstempel wird die aktuelle Systemzeit verwendet, das Format entspricht dem der gleichnamigen C-Funktion.
| |
| |-
| |
| |}
| |
| * Beispiele zur Anwendung von '''close() '''finden sich im Text genügend.
| |
| | |
| Hier soll eine unnütze Anwendung von '''systime() '''den Abschnitt beschließen.
| |
| $ '''awk 'BEGIN { start = systime();
| |
| > for (i = 1; i < 10000000; i++) ;
| |
| > end = systime();
| |
| > print "Gesamtzeit betrug", end - start, "Sekunden.";
| |
| }''''
| |
| Gesamtzeit betrug 6 Sekunden.
| |
| | |
| = Eigene Funktionen =
| |
| * Die eingebauten Funktionen decken einen weiten, aber doch nicht jeden Anwendungsbereich ab.
| |
| * Erst eigene Funktionen eröffnen den Weg zu effizienten Programmen, vor allem dann, wenn identische Abläufe wiederholt im Programm auftreten.
| |
| == Funktionsdefinition ==
| |
| * Eine Funktion muss vor ihrer ersten Verwendung definiert sein.
| |
| * Ihre Definition erfolgt zweckmäßig zu Beginn eines Awk-Skripts, erlaubt ist sie auch zwischen BEGIN-Block und Hauptprogramm bzw. zwischen Hauptprogramm und END-Block.
| |
| Der allgemeine Aufbau einer Funktion ist:
| |
| function name([Parameter [, Parameter] ]) {
| |
| # Anweisungen...
| |
| }
| |
| | |
| * Als Funktionsname sind alle Kombinationen aus Buchstaben, Ziffern und dem Unterstrich zulässig, wobei zu Anfang keine Ziffer stehen darf.
| |
| * In einem Programm darf eine Funktion nicht gleich lauten wie der Bezeichner einer Variable.
| |
| * Als Argumente können beliebig viele Parameter an eine Funktion übergeben werden, wobei das Komma als Trennzeichen dient.
| |
| | |
| Als erstes Beispiel berechnet eine Funktion '''facultiy '''die Fakultät zu einer Zahl x:
| |
| function faculty(x) {
| |
| if (x = 0) return 1;
| |
| return x*faculty(x-1)
| |
| }
| |
| * Unsere Version von '''faculty '''ist rekursiv realisiert, was Awk problemlos akzeptiert.
| |
| * Zur Rückehr aus einer Funktion kann '''return '''mit optionalem Rückgabewert verwendet werden.
| |
| * Fehlt '''return, '''kehrt die Funktion nach Ausführung der letzten Anweisung zurück.
| |
| | |
| == Funktionsaufruf ==
| |
| * Zur Verwendung der Funktion rufen Sie diese einfach auf.
| |
| * Im Gegensatz zu den eingebauten Funktionen darf bei nutzerdefinierten Funktionen kein Leerzeichen zwischen Funktionsname und der öffnenden runden Klammer stehen!
| |
| * Die Angabe von weniger Parametern als definiert ist zulässig; abhängig vom Kontext werden diese als leere Zeichenkette oder als 0 interpretiert.
| |
| | |
| Im folgenden Programm wird der zu berechnende Wert per Kommandozeilenargument übergeben:
| |
| #!/usr/bin/awk -f
| |
|
| |
| function faculty(x) {
| |
| if (x = 0) return 1;
| |
| return x*faculty(x-1)
| |
| }
| |
|
| |
| BEGIN {
| |
| if (ARGC < 2) {
| |
| print "Fehlendes Argument!";
| |
| exit 1;
| |
| }
| |
| if (ARGV[1] !~ /^[[:digit:]]+$/) {
| |
| print "Unzulaessiges Argument!";
| |
| exit 2;
| |
| }
| |
| print faculty(ARGV[1]);
| |
| }
| |
| | |
| == Lokale und globale Variablen, Parameterübergabe ==
| |
| * Damit haben Sie fast das Rüstzeug beisammen, um eigene komplexe Funktionen zu verfassen.
| |
| * Doch die eigenwillige Semantik Semantik der Verwendung von Variablen kann zumindest für den Programmierneuling schnell zu Stolperfalle werden.
| |
| * Mit einer Ausnahme hat eine Funktion grundsätzlichen Zugriff auf alle Variablen, die im Programm bis zum Aufruf der Funktion eingeführt wurden.
| |
| * Solche '''globalen '''Variablen können in der Funktion verändert, gelöscht (nur Array-Elemente [delete]) oder sogar neu eingeführt werden.
| |
| '''Lokale '''Variablen sind einzig jene, die in der Parameterliste benannt wurden.
| |
| * Diese Variablen verdecken ggf. vorhandene gleichnamige Variablen des Programms, sodass Änderungen an diesen in der Funktion »außen« nicht sichtbar werden.
| |
| * Das folgende Programm demonstriert die Verwendung von globalen und lokalen Variablen
| |
| $ '''cat context.awk'''
| |
| #!/usr/bin/awk -f
| |
|
| |
| function context(x, a)
| |
| {
| |
| printf("In der Funktion...\n")
| |
| printf("\tx = %d\n\ta = %d\n\tb = %d\n", x, a, b);
| |
| x = a = b = 99;
| |
| }
| |
|
| |
| BEGIN {
| |
| x = a = 100;
| |
| printf("Vor Aufruf der Funktion...\n")
| |
| printf("\tx = %d\n\ta = %d\n\tb = %d\n", x, a, b);
| |
|
| |
| context(10);
| |
|
| |
| printf("Nach Aufruf der Funktion...\n")
| |
| printf("\tx = %d\n\ta = %d\n\tb = %d\n", x, a, b);
| |
| }
| |
| | |
| $ '''./context.awk'''
| |
| Vor Aufruf der Funktion...
| |
| x = 100
| |
| a = 10
| |
| b = 0
| |
| In der Funktion...
| |
| x = 10
| |
| a = 0
| |
| b = 0
| |
| Nach Aufruf der Funktion...
| |
| x = 100
| |
| a = 100
| |
| b = 99
| |
|
| |
| Das abschließende Beispiel dreht einem das Wort im Munde um...
| |
| function reverse (x) {
| |
| if (length(x) = 0)
| |
| return "";
| |
| return substr(x, length(x), 1) reverse(substr(x,1, length(x)-1));
| |
| }
| |
| | |
| = Weitere Informationen =
| |
| == Intern ==
| |
| # [[gawk:Beispiele]]
| |
| | |
| == Weblinks ==
| |
| # http://de.wikibooks.org/wiki/Awk
| |
| # http://www.gnu.org/software/gawk/manual/
| |
| | |
| [[Kategorie:Linux:Befehl]]
| |
| [[Kategorie:Bash:Scripting]]
| |
| [[Kategorie:Programmierung]]
| |
| [[Kategorie:Linux:Dateien]]
| |
| {{DEFAULTSORT:gawk}}
| |