# AWK-Skript generieren und von einem externen Interpreter ausführen lassen BEGIN { # Variante 1: via Pipe awk = "awk -f -" print "BEGIN { print 1/3 }" | awk close(awk) # Variante 2: via File awk_file = ENVIRON["HOME"] "/awk_file.awk" print "/^root:/" > awk_file close(awk_file) system(sprintf("awk -f %s /etc/passwd", awk_file)) system("rm " awk_file) }
pattern { action statements }
function name(parameter list) { statements }
# summiere und zähle die Werte der Spalte 2 derjenigen Zeilen einer Textdatei, # die mit dem String "daten" beginnen oder dem String "wert" enden function summiere(x) { summe += x anz++ } /^daten|wert$/ { summiere($2) } # Summe und Durchschnitt formatiert ausgeben END { printf("Summe : %6.2f\n", summe) if (anz) { # anz ist ungleich Null printf("Durchschnitt: %6.2f\n", summe / anz) } else { # anz ist Null printf("Durchschnitt: nicht ermittelbar, da 0 Werte addiert wurden\n") } }
awk -f summe_sp2.awk daten_summe_sp2.txt
BEGIN END /regular expression/ relational expression pattern && pattern pattern || pattern pattern ? pattern : pattern (pattern) ! pattern pattern1, pattern2
$1 --> Feld 1 des aktuellen Satzes $NF --> letztes Feld des aktuellen Satzes NF --> Anzahl der Felder des aktuellen Satzes (number of fields) $0 --> die komplette Eingabezeile
# das letzte Feld jeder Eingabezeile ausgeben awk '{ print $NF }' /etc/hosts # die 10. Eingabezeile ausgeben awk 'NR == 10' /etc/passwd # alle Zeilen ausgeben, die entweder "root" oder "false" enthalten # (also Suche wie bei egrep) awk '/root|false/' /etc/passwd # Gesamtzahl der Eingabe-Zeilen ausgeben awk 'END { print NR }' /etc/passwd # das erste und letzte Feld der Eingabezeilen 5 bis 10 ausgeben awk -F: 'NR == 5, NR == 10 { print $1, $NF }' /etc/passwd # das erste und vorletzte Feld der letzten Eingabezeile ausgeben awk -F: 'END { print $1, $(NF-1) }' /etc/passwd # passwd-Eintrag für die aktuelle UID ausgeben awk -F: "\$3 == $UID" /etc/passwd awk -F: -v uid=$UID '$3 == uid' /etc/passwd # Ausgabe von Zeilen mit mehr als 2 Feldern awk 'NF > 2' /etc/hosts # Ausgabe von Zeilen, deren Feld 3 kleiner als 50 ist awk -F: '$3 < 50' /etc/passwd # Ausgabe von Zeilen, deren letztes Feld "false" enthält awk -F: '$NF ~ /false/' /etc/passwd # Ausgabe der Anzahl von Zeilen, deren letztes Feld "false" enthält; # Anmerkung: das Semikolon vor END ist nicht nötig awk -F: '$NF ~ /false/ { anz++ } ; END { print anz }' /etc/passwd # Ausgabe von nicht leeren Zeilen awk NF /etc/hosts # ermittle, wie oft jeder Wert des letzten Feldes der Eingabezeilen vorkommt awk -F: ' { ANZ[$NF]++ } END { for (w in ANZ) printf("%s: %d\n", w, ANZ[w]) } ' /etc/passwd # tausche Feld 1 und 2 der ersten 10 Eingabezeilen; # gib restliche Zeilen unverändert aus awk -F: ' BEGIN { OFS = FS } NR < 11 { t = $1; $1 = $2; $2 = t } 1 ' /etc/passwd # ermittle die längste Eingabe-Zeile awk ' length($0) > max { max = length($0) ; fn = FILENAME ; fnr = FNR ; line = $0 } END { if (fnr) printf("%d Zeichen in Zeile %d in Datei %s\n%s\n", max, fnr, fn, line) } ' /etc/{hosts,passwd} # gib die UIDs der Nutzer, die die bash als Login-Shell haben, fallend sortiert # aus; anschließend wird noch die Anzahl dieser Nutzer ausgegeben awk -F: ' BEGIN { sort = "sort -rn" } $7 ~ /bash/ { print $3 | sort ; anz++ } END { close(sort) ; printf("Anzahl: %d\n", anz) } ' /etc/passwd
Anmerkungen:
# die Datei "getopt.awk" einbinden
@include getopt.awk
# Wirkung der Locale auf AWK-Zahlen awk_command='BEGIN { print 1.5, a, a + 0, a + 1.2, a + 1/3, a "", a == 1.3 }' # Locales: de_DE.UTF-8, de_DE@euro # # Bei numerischen AWK-Konstanten auf der Kommandozeile (Option -v) sowie in # Programm-Quelltexten wird laut Handbuch generell der Dezimalpunkt akzeptiert. LC_ALL=de_DE.UTF-8 awk -v a=1.3 "$awk_command" LC_ALL=de_DE@euro awk -v a=1.3 "$awk_command" # Ausgabe: # 1.5 1.3 1.3 2.5 1.63333 1.3 1 # Durch die Initalisierung einer Variablen (hier konkret "a") auf der # Kommandozeile in den obigen beiden Locales verlor der Dezimalpunkt innerhalb # des AWK-Programms bei Gawk 3.1.3 und 3.1.5 unter Scientific Linux 4.3 seine # Wirkung, so dass Floating-Point-Konstanten nur noch als ganzzahlige # Konstanten gewertet wurden. Die Ausgabe sah dort so aus: # # 1 1.3 1,3 2,3 1,63333 1.3 0 LC_ALL=de_DE.UTF-8 awk "$awk_command" # Ausgabe: # 1.5 0 1.2 0.333333 0 # # Bei den älteren AWK-Versionen sah die Ausgabe so aus: # 1,5 0 1,2 0,333333 0 # Locale: C # Hier trat obiges Problem auch früher nicht auf. LC_ALL=C awk -v a=1.3 "$awk_command" # Ausgabe: # 1.5 1.3 1.3 2.5 1.63333 1.3 1
| Typ | STRING | NUMERIC | STRNUM |
| STRING | String | String | String |
| NUMERIC | String | numerisch | numerisch |
| STRNUM | String | numerisch | numerisch |
Beispiel:
# automatische Datenkonvertierung BEGIN { print "String", 12 "" # durch Verkettung mit dem leeren String print "Zahl", "23" + 0 # durch Addition einer Null }
Beispiel:
# Demo zu lokalen/globalen Variablen # benutzerdefinierte Funktion, die den Inhalt der Variablen "str" an den # globalen Puffer "buffer" anhängt, wobei sie vorher alle Teilstrings löscht, # die aus mindestens 3 aufeinander folgenden Zeichen "x" sowie optional # folgenden Leerzeichen und Tabulatoren besteht function add_to_buffer(str, diff, temp) { # diff und temp sind hier lokal temp = str # alle Teilstrings "xxx" löschen gsub(/xxxx*[ \t]*/, "", temp) # String an den Puffer anhängen buffer = buffer temp # Längendifferenz zwischen Orginal und modifizierter Form errechnen diff = length(str) - length(temp) # die maximale Differenz aktualisieren if (diff > max_diff) { max_diff = diff } } # Zeilen, die "xxx" enthalten, an die Funktion add_to_buffer übergeben /xxx/ { add_to_buffer($0) } # Ausgabe des Puffers sowie der maximalen Längendifferenz END { print "max_diff:", max_diff print "Puffer:", buffer }Aufruf-Möglichkeit:
awk -f lokale_vars.awk daten_lokale_vars.txt
hier findet sich neben der Software auch eine sehr umfangreiche AWK/Gawk-Dokumentation
man awk man gawk info awk info gawkdie Info-Seite ist deutlich umfangreicher als die Manual-Seite und enthält u.a. Beispiele
Stephan Thesing
SED & AWK ge-packt
Editiervorgänge vereinfachen und automatisieren ; Textdateien manipulieren und filtern
zahlreiche Rezepte für Standardaufgaben
mitp-Verlag, 1. Aufl., 2004, 312 S.
ISBN: 3-8266-1427-5