Gym
lesson

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!