Na místě vzorku se mohou vyskytnout jak základní regulární výrazy (RE) podle definice v příkazu ed, tak i rozšířené regulární výrazy podle definice v příkazu grep -E. Regulární výraz se uzavírá do dvojice lomítek. Např. program
/L.*x/ |
vypíše všechny řádky, které obsahují nejprve znak L a potom x. Hledání vyhovujícího vzorku můžeme omezit např. na určitou položku. Např. program
$1 ~ /^[Ll].*x$/ |
vypíše ty řádky, jejichž první položka začíná písmenem L nebo l a končí písmenem x. Operátor !~ vybere ten řádek, který vyhovující vzorek neobsahuje.
Jazyk awk povoluje použití relačních operátorů <, >, ==, != , >= a <=. Např. program
$2 > $1 + 99 |
vypíše ty řádky, jejichž druhá položka je alespoň o 100 větší než položka první. Aritmetické operátory se používají stejné jako v aritmetických expanzích shellu. Např. program
NF % 2 == 0 |
vypíše všechny řádky se sudým počtem položek. Relační operátory se mohou používat jak pro aritmetické srovnávání, tak i pro porovnávání řetězců. Proto např. program
$1 >= "s" |
vybere ty řádky, jejichž první položka začíná znakem s, t, u atd.
Na místě vzorku se může vyskytnout i jejich kombinace spojená booleovskými operátory && (AND - logický součin), || (OR - logický součet) a ! (NOT - negace). Proto např. vzorek
$1 >= "l" && $1 < "o" && $1 !~ /^l.*x$/ |
způsobí výpis řádku, jehož první položka začíná písmenem l až n a zároveň položka nezačíná l a zároveň nekončí x. Operátory && a || se vyhodnocují zleva doprava. Vyhodnocování se zastaví v okamžiku, kdy je výsledek vzorku jasný.
Vzorek, kterým se vybírá akce, se může skládat ze dvou vzorků. Potom levý vzorek určuje první řádek a pravý vzorek určuje poslední řádek, pro který se akce provede. Např. vzorek
/start/,/stop/ |
vypíše všechny řádky od řádku vyhovujícího vzorku /start/ po řádek vyhovující vzorku /stop/. Např. program
NR == 100, NR == 200 |
vypíše záznamy (řádky) 100 až 200.
Identifikátory položek ($1, ...) požívají stejných vlastností jako proměnné. Mohou se používat jak v aritmetickém, tak i řetězcovém kontextu. Lze jim také přiřadit hodnotu. Proto lze napsat např.
{ $2 = NR; print } |
nebo dokonce
{ $1 = $2 + $3; print $0 } |
Odkazy na konkrétní položky se mohou také vyjádřit numerickým výrazem, např.
{ print $i, $(i+1), $(i+n) } |
Jazyk awk dovoluje použít příkazy pro řízení toku obvyklé u vyšších programovacích jazyků. Jde o tyto příkazové konstrukce:
if (podmínka) příkaz [ else příkaz ] while (podmínka) příkaz do příkaz while (podmínka) for (výraz1; výraz2; výraz3) příkaz for (proměnná in pole) příkaz break continue next delete pole[index] exit [ výraz ] { příkaz[; příkaz ... ] } |
Z výše uvedených konstrukcí můžeme vytvořit např. tyto příklady:
{ if ($3 > 1000) $3 = "moc velké" } |
Následující příklad vytiskne vždy jednu položku na jeden řádek:
{ i = 1 while (i <= NF) { print $i ++i }} |
V příkladu jsme si ukázali, že na místě příkazu smí být i více příkazů uzavřených do složených závorek. Následující příkaz provede totéž:
{ for (i = 1; i <= NF; i++) print $i } |
První výraz znamená počáteční přiřazení, druhý výraz představuje podmínku a třetí výraz se opakovaně provádí.
Příkaz break okamžitě ukončí provádění cyklu while nebo for. Příkaz continue přejde ihned na novou iteraci cyklu.
Příkazem next přejdeme na zpracování dalšího řádku (záznamu) vstupu. Příkaz exit je totéž, co načtení konce vstupu (souboru).
Do programu pro awk lze vkládat komentáře. Řádek s poznámkou musí začínat znakem #.
Pole (arrays) se v awk předem nedeklarují. Jako příklad použití pole uveďme
{ x[NR] = $0 } |
Tímto programem načteme celý vstup do jednorozměrného pole a zpracujeme jej až v akci náležející speciálnímu vzorku END.
Prvky pole můžeme indexovat také nenumerickými hodnotami, např. řetězci. Ukažme si opět příklad použití
/modra/ { x["modra"]++ } /cervena/ { x["cervena"]++ } END { print x["modra"], x["cervena"] } |
Pole v awk mohou být obecně n-rozměrná. Jejich prvky se totiž ukládají tak, jak je tomu u asociativních pamětí. S prvkem je uložen i jeho index. V případě více prvkových položek se jednotlivé indexy od sebe oddělují oddělovačem \034 (tuto hodnotu lze změnit proměnnou SUBSEP, viz dále). Potom např.
i = "A"; j = "B"; k = "C" x[i,j,k] = "hello, world\n" |
do paměti uloží index ve tvaru A\034B\034C. V příkazu for můžeme použít zvláštní operátor in následovně:
for (proměnná in pole) ... |
Operátor in v příkazu for zajistí, že proměnné se budou postupně přiřazovat všechny prvky pole. Prvky jsou přiřazovány obecně v náhodném pořadí. Pokud obsah proměnné změníme nebo pokud současně zpřístupňujeme i jiné prvky pole, nastane zřejmě chaos. Je-li pole vícerozměrné, můžeme pro uložení všech indexů (jako řetězce) použít jednu proměnnou.
Operátor in můžeme použít i v příkazech if a while ke zjištění, zda element určitého indexu se v poli nachází. Můžeme napsat
if (hodnota in pole) print pole[hodnota] |
V případě vícerozměrných položek používáme zápis např.
if (("A","B","C") in x) print x["A","B","C"] |
Prvky pole rušíme příkazem delete např. následovně:
delete x["A","B","C"] |
Funkce nebyly do původního awk zahrnuty. Definují se tímto způsobem:
function jméno(seznam_parametrů) { příkazy } |
Při volání funkce se formální parametry nahradí aktuálními. Pole se předávají odkazem, ostatní proměnné hodnotou.
Lokální proměnné se ve funkcích definují dost zvláštním způsobem. Je to zapříčiněno faktem, že původní awk pojem lokální proměnné nezná. Lokální proměnné se definují v rámci seznamu_parametrů tak, že se uvedou na konci a oddělí se více mezerami, např.:
function f(p, q, a, b) { # proměnné a, b jsou lokální ... } /abc/ { ... ; f(1, 2); ... } |
Levá kulatá závorka musí následovat bezprostředně za jménem funkce (bez bílého místa). Tím se odstraní případné nejednoznačnosti syntaxe (možnost záměny s konkatenací).
Z funkce se smí volat jiná funkce a funkce smějí být rekurzivní. Na místě slova function se smí použít jenom func (rozšíření GNU verze).