Osnove awk-a
Cilj lekcije: Naučiti kako awk obrađuje strukturirane podatke — kako da pristupate kolonama, koristite pretragu obrasca (pattern matching), ugrađene varijable i BEGIN/END blokove.
Šta je awk?
awk je alat za obradu tekstualnih podataka organizovanih u redove i kolone. Tehnički je to mali programski jezik, ali za 90% svakodnevnih slučajeva pišeš jednu liniju koju i zapamtiš.
Za razliku od sed-a koji radi na nivou karaktera i linija, awk automatski razbija svaku liniju na polja (kolone) i daje ti pristup svakom polju kao varijabli ($1, $2, ...).
Osnovna sintaksa:
awk 'PROGRAM' fajl.txt
# ili:
awk -F'SEPARATOR' 'PROGRAM' fajl.txt
PROGRAM je oblika: USLOV { AKCIJA }
Polja (kolone) — $1, $2, ..., $NF
awk automatski razbija svaku liniju na polja prema separatoru (podrazumevano: praznine — razmaci i tabovi).
$1— prvo polje$2— drugo polje$3— treće polje$NF— poslednje polje (NF = Number of Fields)$0— cela linija
Primer: ispis prvog polja
echo "Ana Petrović 35" | awk '{print $1}'
# Izlaz: Ana
echo "Ana Petrović 35" | awk '{print $2}'
# Izlaz: Petrović
# Ispis prve i treće kolone
echo "Ana Petrović 35" | awk '{print $1, $3}'
# Izlaz: Ana 35
Primer sa fajlom
zaposleni.txt:
Ana Petrović 35 Beograd
Marko Jovanović 28 Novi Sad
Milica Nikolić 42 Niš
# Ispiši ime i grad (1. i 4. kolona)
awk '{print $1, $4}' zaposleni.txt
Izlaz:
Ana Beograd
Marko Novi Sad
Milica Niš
Prilagođeni separator — opcija -F
Za CSV i druge fajlove sa posebnim separatorima:
# Separator: zarez
awk -F',' '{print $2}' proizvodi.csv
proizvodi.csv:
laptop,85000,5
tastatura,3500,20
mis,1200,50
awk -F',' '{print $1, "cena:", $2}' proizvodi.csv
Izlaz:
laptop cena: 85000
tastatura cena: 3500
mis cena: 1200
Separator dvotačka (/etc/passwd)
# Ispiši korisničko ime i home direktorijum
awk -F':' '{print $1, $6}' /etc/passwd
Pretraga obrasca (pattern matching) — uslovno izvršavanje
awk može da filtrira linije prema obrascu pre nego što primeni akciju:
# Ispiši samo linije koje sadrže "ERROR"
awk '/ERROR/ {print $0}' app.log
Ekvivalentno grep "ERROR" app.log, ali sa mogućnošću daljih operacija:
# Ispiši vreme (treće polje) samo za ERROR linije
awk '/ERROR/ {print $3}' app.log
Negacija obrasca
# Ispiši sve linije koje NE sadrže "DEBUG"
awk '!/DEBUG/ {print}' app.log
Poređenje vrednosti polja
# Ispiši zaposlene starije od 30
awk '$3 > 30 {print $1, $3}' zaposleni.txt
Izlaz:
Ana 35
Milica 42
# Ispiši redove gde je cena veća od 10000
awk -F',' '$2 > 10000 {print $1}' proizvodi.csv
Kombinovanje uslova
# AND uslov
awk '$3 > 25 && $3 < 40 {print $1}' zaposleni.txt
# OR uslov
awk '/ERROR/ || /WARN/ {print}' app.log
Ugrađene varijable
awk ima nekoliko ugrađenih varijabli koje su uvek dostupne:
| Varijabla | Značenje |
|---|---|
NR |
Redni broj trenutne linije (Number of Records) |
NF |
Broj polja u trenutnoj liniji (Number of Fields) |
FS |
Separator polja (Field Separator, podrazumevano praznine — razmaci i tabovi) |
OFS |
Separator polja u izlazu (Output Field Separator) |
RS |
Separator redova (Record Separator, podrazumevano ` |
| `) | |
ORS |
Separator redova u izlazu |
FILENAME |
Ime trenutnog fajla |
Primer sa NR — numerisanje linija
awk '{print NR, $0}' fajl.txt
Izlaz:
1 Ana Petrović 35 Beograd
2 Marko Jovanović 28 Novi Sad
3 Milica Nikolić 42 Niš
Primer sa NF — poslednje polje
# Ispiši poslednje polje svake linije
awk '{print $NF}' fajl.txt
# Ispiši linije koje imaju tačno 4 polja
awk 'NF == 4 {print}' fajl.txt
Primer sa NR za opseg linija
# Ispiši linije od 5 do 10
awk 'NR >= 5 && NR <= 10 {print}' fajl.txt
Postavljanje OFS
# Promeni separator u izlazu na zarez
awk 'BEGIN{OFS=","} {print $1, $3}' zaposleni.txt
Izlaz:
Ana,35
Marko,28
Milica,42
BEGIN i END blokovi
BEGIN blok se izvršava pre čitanja ijedne linije fajla.
END blok se izvršava posle svih linija.
Korisno za: inicijalizaciju varijabli, ispis zaglavlja, ispis ukupnih vrednosti.
Primer: zaglavlje i zbir
awk -F',' '
BEGIN {
print "=== Izveštaj o prodaji ==="
ukupno = 0
}
{
ukupno += $2
print $1 ": " $2 " din"
}
END {
print "==========================="
print "Ukupno: " ukupno " din"
}
' proizvodi.csv
Izlaz:
=== Izveštaj o prodaji ===
laptop: 85000 din
tastatura: 3500 din
mis: 1200 din
===========================
Ukupno: 89700 din
Varijable i aritmetika
awk podržava varijable i matematičke operacije:
# Izračunaj prosečnu starost
awk '{suma += $3} END {print "Prosek:", suma/NR}' zaposleni.txt
# Nađi maksimalnu vrednost
awk 'BEGIN{max=0} $2 > max {max=$2; ime=$1} END {print "Najskuplji:", ime, max}' \
proizvodi.csv
Stringovi i konkatenacija
awk '{poruka = "Zaposleni: " $1 " " $2; print poruka}' zaposleni.txt
Praktični primeri sa log fajlovima
Apache access.log
Format linije:
192.168.1.10 - - [15/Jan/2024:14:23:45 +0000] "GET /index.html HTTP/1.1" 200 1234
# Ispiši IP adrese i URL-ove
awk '{print $1, $7}' access.log
# Ispiši samo zahteve sa greškom 404
awk '$9 == 404 {print $1, $7}' access.log
Filtriranje po statusu koda
# Sve 5xx greške (serverske greške)
awk '$9 >= 500 && $9 < 600 {print $1, $7, $9}' access.log
Asocijativni nizovi — brojanje po ključu
awk podrzava nizove indeksirane stringovima (asocijativni nizovi). Klasican primer: prebrojati koliko puta se pojavljuje svaka vrednost:
# Prebroj koliko puta se pojavljuje svaki HTTP status kod
awk '{status[$9]++} END {for (s in status) print s, status[s]}' access.log
# Prebroj zahteve po IP adresi
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log \
| sort -rn | head -10
Rezime
| Sintaksa | Šta radi |
|---|---|
awk '{print $1}' |
Ispiši prvo polje |
awk '{print $NF}' |
Ispiši poslednje polje |
awk -F',' |
Postavi separator na zarez |
awk '/ERROR/' |
Filtruj linije koje sadrže ERROR |
awk '$3 > 30' |
Filtruj po vrednosti polja |
awk 'NR==5' |
Samo 5. linija |
awk 'BEGIN{} {} END{}' |
Inicijalizacija, obrada, završetak |
awk '{suma+=$2}' |
Akumulacija vrednosti |
awk '{arr[$1]++}' |
Asocijativni niz — brojač |
Sada kada poznajete sort, uniq, cut, tr, sed i awk, možete samostalno rešavati složene zadatke obrade teksta — baš kao u sledećoj vežbi!