Awk

O Awk

AWK je jazyk pro zpracování řetězců. Používá se na podobné věci jako sed, jen je to trochu více programovací jazyk.

SYNOPSIS

awk [option] {-f p_soubor|program} [soubor ...]

OPTIONS

-f p_soubor
Soubor s programem AWK
program
retezec, ktery obshuje program awk
soubor
Jmena zpracovananych souboru. Nejsou-li uvedeny, zpracovava se standardni vstup.

EXAMPLES

$ # vytiskneme 1 a 5 sloupec z vystupu programu ps
$ ps ax | awk '{print $1 " " $5}'
...
32536 ps
32537 awk
$ # vytiskne prvni a treti sloupec z /etc/passwd
$ # jako oddelovac pole se bere :
$ awk -- 'BEGIN {FS=":"} {print $1 " " $3}' </etc/passwd
...
wwwrun 30
petr 1000
tomcat 114

Struktura zpracovávaných souborů

Záznamy a pole

Implicitni oddelovac zaznamu ve zpracovavanych souborech je znak "novy radek" (zaznamem je tedy cela radka). Kazdy vstupni zaznam je dale rozdelen na pole. V normalnim pripade jsou pole od sebe oddelena mezerami nebo tabulatory, ale lze definovat i jinne oddelovace.

Cislo aktualniho zaznamu je ulozeno v promenne NR.
Jednotliva pole jsou pristupna v programu awk pomoci promennych $1 (prvni pole), $2 (druhe pole) ….
V $0 je ulozeny cely vstupni zaznam (obvykle radka).

Struktura programu

Následující část popisuje strukturu skriptu AWK, která se píše do souboru předávaného volbou -f nebo se píše rovnou na příkazovou řádku (do jednoduchych uvozovek).

Na příkazové řádce používejte jednoduché uvozovky pro zápis programu, jinak se pokusí shell interpretovat $1, $2 atp. jako proměnné …

Bloky programu

vzor {akce} [vzor {akce} ...]
vzor
Program se aplikuje pouze na radky, ktere odpovidaji vzoru (reg. vyraz). Vzor je nepovinny. V pripade, ze neni uveden, provede se akce pro vsechny radky. Radek nevyhovujici zadnemu vzoru se ignoruje.
{akce}
Akce je take nepovinna. Neni-li uvedena, radky vyhovujici danemu vzoru se jen vytisknou na standardni vystup (defaultni akce je {print})

Vzory

Jako vzor lze pouzit logicky vyraz nebo regularni vyraz. Operator ~ testuje, zda pole nebo promenna vyhovuje regularnimu vyrazu. Operator !~ je negaci operatoru ~, tedy testuje na neshodu s regularnim vyrazem.

V logickych vyrazech je mozne pouzivat nasledujici relacni operatory:

OperátorVýznam
<mensi nez
<=mensi nebo rovne
==rovno
!=neni rovno
>=vetsi nebo rovno
>vetsi nez
||logicky soucet (nebo - or)
&&logicky soucin (a - and)
vzor ? vzor1 : vzor0Pokud radka odpovida vzoru, vyhodnoti se jeste vzor1, jinak vzor0

Druhy vzorů

{ … }
(bez vzoru) Vykona se pro vsechny radky
BEGIN { … }
Akce spojene s timto vzorem se vykonaji pred zahajenim ostatnich akci awk.
END { … }
Akce se provedou po ukoncini zpracovani vsech osatnich akci awk.
/reg vyraz/ { …}
Akce se provedou na zaznamech (radkach), ktere odpovidaji vzoru
(logicky vyraz) { … }
Akce se provedou, pokud se logicky vyraz vyhodnoti jako pravdivy
vzor, vzor { … }
Carka je operator rozsahu. awk zpracovava interaval radek, ktery zacina radkem vyhovujici prvnimu vzoru a konci radkem, ktery vyhovuji druhemu vzoru. Pote, co awk nalezne druhy vzor (dokonci zpracovavani rozsahu), opet zacina hledat prvni vzor.

Examples

awk '$1~/^[Aa]/ {print}'
Vybira vsechny radky, ve kterych prvni pole odpovida regularnimu vyrazu ^[Aa]
awk '$1 < 5 ? $1 >1 : $1 > 8 {print}' cisla.txt
Vybira radky, ve kterych, pokud je prvni sloupec mensi nez 5 a vetsi nez 1 nebo je vetsi nez 5 a vetsi nez 8. (Tj. napr. cisla 2,3,4,9,10)

Akce

Odkazy na pole v záznamu

Záznam je defaultně řádka (oddělovač záznamů je defaultně znak "nová řádka").

Oddelovac poli v zaznamu je defaultne mezera. Je ulozen ve specialni promenne FS, kterou je mozno nastavit na jinou hodnotu. Oddelovac poli na vystupu je ulozen v promenne OFS. (Pouziva se u funkce print, kde se argumenty oddeluji carkou - misto carky se pouzije oddelovac OFS).

$1 $2 $3 …
odkazy jednotlive pole
$0
cely zaznam (cela radka)
NF
pocet poli ({printf $1, $NF} vytiskne prvni a posledni pole oddelene mezerou)

Akce - telo awk programu

Akce je to, co je uvnitr spicatych zavorek {}.
Neni-li uvedena, predpoklada se {print} (tj. vypis celeho radku). Akce se provede na kazdem radku, ktery vyhovi vzoru uvedenem pred akci. Pokud neni vzor uveden, provede se na kazdou radku. Pokud je vzor BEGIN resp. END, provede se pred zacatkem cteni radek, resp. po skonceni.

Uvnitr akce awk lze standardni vystup presmerovat do souboru (>), pripojit k souboru (>>) nebo spojit se vstupem jineho programu (|).

Je-li v {} vice prikazu, jsou od sebe oddeleny strednikem.

Komentar

Vše za znakem # uvnitr akce az do konce radky je chapano jako komentar. (Hodi se pro programy zapsane v souboru, na prikazove radce se vyuzije stezi).

Promenne

Promenne se deklaruji a inicializuji svym prvnim pouzitim. Awk ma nekolik zabudovanych promennych:

NR
cislo aktualniho zazamu
$0
aktualni zaznam (jako jedna promenna)
N
pocet poli v aktualnim zaznamu
$1,$2..
jednotliva pole v aktualnim zaznamu
FS
oddelovac vstupnich poli (implicitne mezera nebo tabulator)
RS
oddelovac vstupnich zazamu (implicitne "novy_radek" )
OFS
oddelovac vystupnich poli (implicitne mezera)
ORS
oddelovac vystupnich zazanamu (implicitne "novy radek")
FILENAME
jmeno aktualniho vstupniho souboru

Hodnoty RS, ORS, FS a OFS lze v programu zmenit.

FUNKCE

Awk ma definovano nekolik funkci pro praci s cisli a retezci:

length(str)
pocet znaku v argumentu str. Neni-li argument uveden, predpoklada se aktualni vstupni zaznam ($0)
int(num)
vraci celociselnou hodnotu num.
index(str1,str2)
vrati 0, pokud str2 neni obsazen v str1, jinak vrati pozici, v niz je umisten str2 v retezci str1. (prvni znak zacina jednickou, ne nulou)
split(str,arr,del)
ulozi prvky argumentu str, oddelene od sebe oddelovacem del do prvku pole arr[1]...arr[n], a vrati poecet prvku v poli.
sprintf(fmt,args)
argumenty args se zformatuji podle formatu fmt a vrati se vytvoreny retezec.
substr(str,pos,len)
vrati se podretezec retezce str zacinajici na pozici pos o delce len znaku.
exp(x)
exponencialni funkce.
log(x)
prirozeny logaritmus.
sqrt(x)
druha mocnina.
atan2(y,x)
arcus tangens podilu y/x
cos(x)
cosinus x
sin(x)
sinus x
getline
cte dalsi zaznam
gsub(RE,nahr,[str])
provadi globalni substituci vzoru RE retezcem nahr v retezci str; pokud argument str neni uveden, predpoklada se $0.
rand
nahodne cislo v intervalu 0 az 1 vcetne.

Spoustu dalších funkcí můžete najít v manuálové stránce k awk.

Funkce printf

Funkci printf lze pouzit vsude tam, kde se pouzije funkce print. Umoznuje ridit format vystupu podobne, jako printf z jazyka C.

printf "ridici_retezec" arg1, arg2, ..., argn
"ridici_retezec"
urcuje, jak se budou zobrazovat nalsedujici argumenty arg1 až argn.

Ridici retezec muze obsahovat:

metaznakyvyznam
\""
\\\
\nprechod na zacatek noveho radku
\ttabulator
\bposun o znak zpet (doleva)
\rnavrat na zacatek aktual. radku
\fprechod na novou stranku

Dale muze "ridici_retezec" obsahovat specifikace konverze:

%[-][x][.y] konverzni_znak
-znamena zarovnani zleva
xminimalni sirka pole
.ypocet mist vpravo od desetinne carky

Konverzni znak muze byt nasledujici:

ddekadicky
eexponencialni notace
fcislo s pohyblivou radovou carkou
gkratsi varianta z f nebo e
oosmickove cislo bez znamenka
sretezec znaku
xhexadecimalni cislo bez znamenka

Operátory

operatorVýznam
* nasobeni
/ deleni
% zbytek po deleni
+ scitani
= prirazeni
++ pricteni hodnoty 1 k promenne, ktera predchazi operator
-- odecteni …
+= pricteni nasledujiciho vyrazu k promenne predchazejici operator
-= odecteni …
*= vynasobeni ... a ulozeni vysledku do promenne predchazejici operator
/= deleni promenne predchazejici operator nasledujicim vyrazem a ulozenim do promenne predchazejici operator
%= zbytek po deleni …

Řídící struktury

Pro rizeni cinnosti lze vyuzivat ridici struktury, ktere jsou podobne jako ty v jazyku C.

if (podminka) prikaz1
else prikaz2
for (inicializace ridici promenne cyklu; podminka; zmena ridici promenne cyklu)
    prikaz
while (podminka) prikaz
break
ukoncuje cykl
continue
zacina dalsi iteraci cyklu
next
zacne se zpracovavat dalsi vstupni zaznam
exit
prejde se na vzor END

EXAMPLES

$ awk '{if ($1>5) print $1 " je vetsi nez 5"; else $1 " je mensi nez 5"}' soubor.txt

Pokud zaznam nezacina cislem, budeme zpracovavat dalsi zaznam (dalsi radku), dokud se nenajde radka zacinajici cislem.
Program je ulozen v souboru program.awk.

{
    while ($1 !~ /^[0-9]/)
    {
        getline
    }
    print $0
}
$ awk -f program.awk soubor.txt

Program na tisknuti pouze sudych poli:

{
    i=1;
    while(i++ <= NF)
    {
        if (i%2) {
            getline
            continue;
        }
        else print $0
    }
}

Zaznamy zacinajici teckou se ignoruji:

$ awk '{ if($1 ~ /^\./) next; else print }' soubor.txt

Vytisteni poli zaznamu v obracenem poradi:

$ awk '{ for(i=NF;i>0;i--) printf "%s ", $i; print "" }' soubor.txt

Definice uživatelské funkce

function jmeno_funkce(arg, ...) { prikazy }
  • Volani funkce muze byt uvedene jeste pred vlastni definici
  • Mezi jmenem funkce a levou zavorkou nesmi byt zadna mezera
  • Je-li argumentem pole, predava se odkazem (ve funkci muzeme zmenit hodnotu prvku pole a tato zmena se projevi v poli vně tela funkce). Obycejne promenne se predavaji hodnotou - pracujeme s jejich kopii a vne funkce se jejich hodnota nemeni.
  • return x; - nektere funkce mohou takto vracet hodnotu
  • lokalni promenne jsou promenne odsazene v seznamu argumentu extra mezerou (divny, ale je to tak)

EXAMPLES

Definujeme funkci hledej, ktera v poli jmena hleda retezec ulozeny v argumentu kdo. Pokud retezec v poli nalezne (prave tento retezec), vrati jeho index, jinak vrati hodnotu -1. Argument uk se pouziva jako lokalni promenna.

{
    jmena[0] = "Petr"
    jmena[1] = "Tomas"
    print $1, hledej($1, jmena)
}

function hledej(kdo,jmena,  uk)
{
    for(uk=0;jmena[uk];uk++)
        if(index(jmena[uk],kdo)==1 && length(jmena[uk])==length(kdo))
            return uk
        return -1
}

Pokud index vrati hodnotu 1, retezec kdo je zacatkem retezce jmena[uk]. Pokud maji i stejnou delku, shoduji se.

Asociativni pole

Všechny proměnné typu array jsou v awk asociativní (indexované řetězci).
Prirazeni hodnoty prvku asociativniho pole se provadi obdobne, jako kdyz prirazujeme hodnotu nejake promenne:

pole[index] = hodnota
print pole[index]

Speciální operátor in se dá použít pro zjištění, zda je v poli nějaký index:

if("index" in pole)
    print pole["index"]

Existuje i specialni tvar prikazu for, ktery iteruje pres asociativni pole:

for (prvek in pole)
    print prvek

Prvek je promenna, ktera nabyva hodnoty kazdeho indexu pole. Pole neni setridene, proto neni mozne se spolehat na poradi prvku v poli.

$ awk 'BEGIN { mesic["Leden"]=31; \
mesic["Unor"]=28; \
mesic["Brezen"]=31; \
.
.
mesic["Prosinec"]=31 }
END { for(i in mesic) print i, "ma " mesic[i] "dnu" }'


Leden ma 31dnu
Unor ma 28dnu
.
.
Prosinec ma 31dnu
Brezen ma 31dnu
Prikaz awk vykona jen akci pred ctenim souboru (BEGIN) a pak po cteni souboru (END), takze vlastne neni potreba zadny soubor. Po zadani awk programu staci stisknout CTRL+d, cimz se ukonci standardni vstup a prikazy se vykonaji.

Examples

Vytiskne se predposledni a posledni pole kazdeho radku souboru data. Jednotliva pole budou navystupu oddelena dvojteckou.

$ awk 'BEGIN {OFS=":"} {print $(NF-1), $NF}' soubor.txt

Pokud radek obsahuje jen jedno pole, radek se zobrazi dvakrat oddelen dvojteckou: nejprve $0, potom $1.

Sectou se hodnoty prvniho pole ve vsech radcich souboru soubor.txt a nakonec se vytiskne prumerna hodnota tohoto pole.

$ awk '{s+=$1} END {print "Celkem: ", s, "Prumer: ", s/NR}' soubor.txt

Vytiskne vsechny radky ze souboru, ve kterych se prvni pole lisi od prvniho pole predchoziho radku.

$ awk 'NR==1 || $1!=pred  {print; pred=$1}' soubor.txt
Komentář Hlášení chyby
Created: 11.9.2005
Last updated: 13.7.2013
Tato stánka používá ke svému běhu cookies, díky kterým je možné monitorovat, co tu provádíte (ne že bych to bez cookies nezvládl). Také vás tu bude špehovat google analytics. Jestli si myslíte, že je to problém, vypněte si cookies ve vašem prohlížeči, nebo odejděte a už se nevracejte :-). Prohlížením tohoto webu souhlasíte s používáním cookies. Dozvědět se více..