Gawk/Beispiele
awk ist eine Programmiersprache zur Veränderung von Textdateien
Einführung
Erstellt von Alfred V. Aho, Peter J. Weinberger und Brian W. Kernighan
- Basiert auf der Programmiersprache C
Kann aufgerufen werden in
- der Shell-Konsole
- Shell-Scripten
- awk-Scripten
awk wartet auf Daten von Eingabeströmen aus Dateien oder aus der Standardeingabe
- awk arbeitet Zeile für Zeile bis zum Dateiende
Syntax & Aufbau
Allgemeine Syntax:
$ awk 'Programm' Datei oder $ awk -f Programmdatei Datei
Der Aufbau eines awk-Programms:
- Optionaler Anfang(BEGIN), der einmalig ausgeführt wird
- Hauptprogramm aus Anweisungen, das für jede Eingabezeile erneut ausgeführt wird
- Optionales Ende(END), der einmalig ausgeführt wird
Eine Anweisung wiederum:
- hat ein optionales Muster, meist Reguläre Ausdrücke
- gefolgt von einem Kommandoblock in geschweiften Klammern
/Muster/ {Kommando;
Kommando;
...
}
Ein Beispiel:
BEGIN{
print "Zählen von Eingabezeilen";
zaehler=0;
}
{ zaehler++; }
END{
print "Ergebnis: " zaehler;
}
Anwendungsfälle
Beispieldatei
1. Hier ist ein Text mit Inhalt A Eine Zeile 2. Tim & Struppi A Was war das? B Aktion und Reaktion 3. Reisig schmeckt am Besten A Nein, stimmt nicht B Doch !
Einzeiler
Anzahl der Zeilen ausgeben
$ awk 'END {print NR}'
10
Zeile fünf ausgeben
$ awk 'NR == 5' ---------------------- A Was war das?
Zeilen ab Zeile sechs ausgeben
$ awk 'NR > 6' ---------------------- 3. Reisig schmeckt am Besten A Nein, stimmt nicht B Doch !
Zeilen ausgeben mit mehr als 4 Felder
$ awk 'NF > 4' ---------------------- 1. Hier ist ein Text mit Inhalt 3. Reisig schmeckt am Besten
Zeilen nummerieren
$ awk '{print NR, $0}'
-----------------------
1 1. Hier ist ein Text mit Inhalt
2 A Eine Zeile
3
4 2. Tim & Struppi
5 A Was war das?
6 B Aktion und Reaktion
7
8 3. Reisig schmeckt am Besten
9 A Nein, stimmt nicht
10 B Doch !
Weitere Beispiele
| awk '{print $2, $3}' my.txt | print 2nd & 3rd fields separated by space |
| awk '{print $2 "," $3}' my.txt | print 2nd & 3rd field separated by comma |
| awk '$2 >100' my.txt | print lines where 2nd field is> 100 |
| awk '$1==100' my.txt | print lines where 1st field equals to 100 |
| awk '/error/' my.txt | print lines containing the word 'error' |
| awk '{sum=$1+$2; print sum]' my.txt | sum up 1st & 2nd fields of each line |
| awk '{print NR, $0}' my.txt | add line number to each line and print it |
| awk '[print NF}' my.tzt | print the number of fields in each line |
| awk '{print $1, $NF}' my.txt | print 1st & last fields |
| awk '{s+=$2; c++} END {print s/c}' my.txt | compute average of 2nd field |
| awk '$1>100 {s+=$2; c++} END {print s/c}' my.txt | average with condition |
| awk '{print toupper($2)}' my.txt | print 2nd field in uppercase |
| awk '$1=="ERR" {print $2}' my.log | print 2nd field if 1st field is "ERR" |
| awk '{print "Name:", $1, "Age:", $2}' my.txt | formatted printing |
| awk -F"," {print $2, $3}' my.csv | use comma "," as a field separator |
| awk '{print substr($2,1,3)} my.txt | extract substring from 2nd field |
| awk function sq(x) {return x*x} {print sq($2)}' | my.txt define a function |
| awk '!seen[$1]++' my.txt | remote duplicate lines based on 1st field |
| awk 'length($2) > 3' my.txt | print lines where length of 2nd field > 3 |
| awk '$1 ~ /ERR/' my.log | print lines where 1st field matches pattern |
| awk '$1 ~- /ERR/' my.log | print lines where 1st field doesn't match pattern |
| awk '$1 ~ /*[0-9]+$/' my.log | print lines where 1st field is a numeric value |
Operatoren
- Identisch mit C
- Wichtigster Operator: "~" prüft Übereinstimmung mit Regulären Ausdrücken
- "==" vergleicht nur mit Konstanten und Variablen
Wichtige Variablen
gawk arbeitet unter der Annahme, dass die Eingabe strukturiert ist
- Jedes Feld ist eine Zeichenfolge, die durch Feldseperatoren (meistens Leerzeichen oder Tabulator) begrenzt ist
- $ ist der Feldoperator
- $1 ist das erste Feld.
- $0 steht für die gesamte Zeile, die gerade bearbeitet wird.
$ awk '{print $1}'
-----------------------
1.
A
2.
A
B
3.
A
B
- $NF steht für das letzte Feld
$(NF-1) gibt das vorletzte Feld wieder. (Achtung: Bei Leerzeilen führt es zu Laufzeitfehler)
$ awk '{print $(NF-1)}'
-----------------------
mit
Eine
awk: run time error: negative field index $-1
FILENAME="beispiel2" FNR=3 NR=3
Richtig angewandt:
{
if($0 ~ /^$/)
{
print $0
}
else
{
print $(NF-1)
}
}
mit Eine & war und am stimmt Doch
Weitere Anwendungen
Zählt Dateien im Verzeichnis usr und berechnet den Speicherbedarf:
$ ls -l /usr | awk '{ ++files; sum+=$5 } END { print sum, "Bytes in", files, "Dateien"; }'
------------------------
139264 Bytes in 12 Dateien
Aktueller Fall: Fragen und Antworten mit einer Nummer markieren, um so ihre Zugehörigkeit zu zeigen:
{
if($1 ~ /^[0-9]./)
{
++row;
}
print row, $0;
}
Ähnlich wie der davor, nur das die Fragen und Antworten jeweils in eigene Dateien gepackt werden. Desweiteren werden auch die Zahlen und Buchstaben vor den Fragen bzw. Antworten entfernt:
{
if($1 ~ /^[0-9]./)
{
++row;
$1 = "";
print row, $0 >> "fragen.txt";
}else
{
$1 = "";
print row, $0 >> "antworten.txt";
}
}