Další Předchozí Obsah

11. Jazyk textových manipulací awk

Awk je programovaci jazyk pro praci s textem. V textove orientovanem UNIXu jej pouzivame take pro automatickou konstrukci prikazu, prikazovych souboru a predzpracovani vstupnich dat. Nazev Awk pochazi ze jmen jeho autoru: Alfred V. Aho, Peter J. Weinberger a Brian W. Kernighan. Interpretem tohoto jazyka je prikaz (program) awk. Jeho verzi se vsak vyskytuje vice. Nejvice funkci ma zrejme implementace awk z projektu GNU (gawk) a ji je nasledujici text venovan.

11.1 Pouziti awk

Prikaz se spousti nasledujicim zpusobem:

$ awk program [soubory]

Program muzeme take cist ze souboru, potom zadame:

$ awk -f soubor [soubory] 

Program awk cte radky bud ze zadanych souboru nebo ze standardniho vstupu. Vystup smeruje na standardni vystup.

Kdyz napisete awk program a chcete, aby se startoval jako normalni program na zacatek date:


#! awk -f

To zaridi, ze se vas program tvari jako normalni seriozni programek.

11.2 Struktura programu

Program pro awk se tvori posloupnosti prikazu va tvaru:

vzorek { akce }
vzorek { akce }
atd.  

V kazdem radku ctenem ze vstupu se hleda urceny vzorek. Pokud se najde, provede se s radkem zadana akce. Pote, co se pouziji vsechny vzorky, precte se ze vstupu dalsi radek a operace se opakuji.

Jak vzorek, tak akce se smi vynechat. Nelze vsak vynechat oboji soucasne. Pokud neni ke vzorku urcena akce, potom se vyhovujici radek zkopiruje na vystup. Pro radek vyhovujici vice vzorkum bude akce provedena vicekrat. Radek nevyhovujici zadnemu ze zadanych vzorku se ignoruje.

Pokud vynechame vzorek, potom se akce provede pro kazdy nacteny radek. Popis akce se musi uzavrit do slozenych zavorek '{ }'. Tim se popis akce rozpozna od popisu vzorku.

11.3 Zaznamy a polozky

Vstup, ktery awk cte, delime do zaznamu (records) ukoncenych oddelovacem zaznamu. Implicitnim oddelovacem zaznamu je znak noveho radku. V tomto pripade je zaznamem jeden radek. Cislo aktualniho zaznamu awk udrzuje v promenne NR.

Kazdy zpracovavany zaznam se deli do polozek (field). Polozky se implicitne oddeluji bilym mistem (mezera, tabulator), lze vsak explicitne nastavit jinou hodnotu oddelovace polozek. Na jednotlive polozky se odkazujeme $1, $2 atd. Udaj za znakem dolar je cislo (ne jenom cislice). Identifikatorem $0 se odkazujeme na cely zaznam. Pocet polozek v aktualnim zaznamu je ulozen v promenne NF.

Chceme-li zmenit implicitni nastaveni oddelovacu zaznamu a polozek, nastavime novou hodnotu do promenne: RS pro oddelovac zaznamu a FS pro oddelovac polozek. Obsah techto promennych muzeme zmenit obecne na regularni vyraz (v jinych verzich awk pouze na libovolny jeden znak). Oddelovac polozek muzeme take nastavit na prikazovem radku pri spousteni awk volbou -Fc, kde c je oddelovac polozek.

Je-li oddelovac zaznamu prazdny, potom se jako oddelovac chape prazdny radek na vstupu. Oddelovaci polozek potom jsou znaky mezera, tabulator a novy radek.

V promenne FILENAME je ulozeno jmeno aktualniho vstupniho souboru ('-' v pripade standardniho vstupu).

11.4 Vystup

Nejjednodussi program, ktery opise standardni vstup na standardni vystup, je nasledujici:

... | awk '{ print }' | ...

Vzorek jsme vynechali, a proto se akce print provede pro vsechny vstupujici radky. Akce print bez parametru opise cely radek na vystup. Uzitecnejsi bude vybrat si urcite polozky a tyto vypsat, napr. prvni dve polozky v opacnem poradi: Takovy zapis akce na prikazovem radku spoustejicim awk musi byt nutne uzavren do dvojice apostrofu, aby nedoslo k expanzi dvojic znaku $1 a $2 na pozicni parametry shellu, ale aby se v nezmenene podobe predaly awk.

Polozky oddelene v zapisu akce print carkou se na vystupu oddeli aktualne nastavenou hodnotou oddelovace polozek. Polozky oddelene pouze mezerou se spoji bez oddelovace. Vyzkousejme si:


{ print $2 $1 }

Akce print umi vypisovat i obsahy promennych a textove retezce, napr.:

{ print "Cislo zaznamu=" NR, "Pocet polozek=" NF, $0 } 

Takto zadany program pred kompletnim zaznamem vypise cislo zaznamu a pocet polozek v aktualnim zaznamu.

Vystup muzeme rozdelit i do vice vystupnich souboru. Napr. program:


{ print $1 >"soubor1"; print $2 >"soubor2" }  

zapise prvni polozku do souboru soubor1 a druhou polozku do souboru soubor2. Lze pouzit i zapis >>. Potom se do souboru pridava za konec. Jmeno souboru muze byt promenna, obsah zapisovany do souboru muze byt konstanta. Muzeme tedy napsat napr.:

{ print "nesmysl" >>$2 } 

Jako jmeno souboru se pouzije obsah druhe polozky (pozor, nesmi byt prazdna). V tomto priklade bude pocet radku v jednotlivych souborech znamenat cetnost slov ve druhem poli.

Podobne lze vystup z akce print predat rourou procesu. Napr. poslat postou na adresu 'zaznamenej':


{ print | "mail zaznamenej" }  

Pokud si tento priklad vyzkousime, zjistime, ze se procesu preda cely vstup naraz, tj. nepredava se po jednotlivych zaznamech a navic se preda az po nacteni konce vstupu.

Pomoci promennych OFS a ORS muzeme samostatne nastavit oddelovace pouze pro vystup. Obsahem OFS se oddeli vypisovane polozky a obsahem ORS se oddeli vypisovane zaznamy.

Jazyk awk take poskytuje moznost formatovanych vystupu pomoci akce printf. Tato akce se zapisuje nasledujicim zpusobem:


printf format, vyraz, vyraz, ...

Popisovacem format sdelime strukturu vystupu a prostrednictvim nadefinovane struktury vypiseme jednotlive vyrazy. V popisovaci format se pouziva stejna syntaxe jako v jazyce C. Uvedme si ve strucnosti moznosti:

Do retezce format vkladame text, ktery se ma vypsat. Na mista, kde se ma vypsat vysledek vyrazu, vlozime popisovac ve tvaru:


%priznakysirkapresnosttypkonverze 

Prvnimu popisovaci (kazdy popisovac zacina vzdy znakem %) se priradi vysledek prvniho vyrazu, druhemu popisovaci vysledek druheho vyrazu atd. Jednotliva pole popisovace maji tento vyznam (vsechna pole vyjma konverze jsou nepovinna):

Na miste konverze se smeji pouzit tyto symboly:

Akce printf negeneruje zadne vystupni oddelovace. Vsechny se museji specifikovat ve formatu. Uvedme si priklad pouziti:


{ printf "Prumer=%8.2f, pocet pokusu=%10ld\n", $1, $2 }

Prvni polozka se vytiskne jako cislo v pohyblive radove carce celkem na 8 znaku se dvema cislicemi za desetinnou teckou. Druha polozka se vytiskne jako long integer na 10 znaku. Znak \n predstavuje novy radek.

11.5 BEGIN a END

BEGIN a END jsou specialnimi pripady vzorku. Vzorek BEGIN specifikuje akci, ktera se ma provest drive, nez se precte prvni zaznam vstupu. Naopak vzorek END popisuje akci, ktera se provede po zpracovani posledniho cteneho zaznamu. Timto zpusobem muzeme ridit zpracovani pred a po cteni zaznamu.

Jako priklad uvedme nastaveni specifickeho oddelovace polozek a vytisknuti poctu nactenych zaznamu:


BEGIN { FS = ":" }
...zbytek programu...
END { print NR } 

BEGIN musi byt jako prvni vzorek (je-li uveden), END musi byt poslednim vzorkem.

11.6 Akce

Akce programu awk je posloupnost prikazu vzajemne oddelenych novym radkem nebo strednikem.

11.7 Promenne, vyrazy a prirazeni

Jazyk awk promenne zpracovava podle kontextu: bud jako numericke hodnoty (v pohyblive radove carce), nebo jako retezce znaku. Retezce se na numericke hodnoty prevadeji podle potreby. Potom napr.

x = 1

je typicky numericky prirazovaci prikaz, ale v prikazu

x = "3" + "4" 

se retezce prevedou na numericke hodnoty a promenne x se priradi numericka hodnota 7. Retezce, ze kterych nelze ziskat numerickou hodnotu, maji hodnotu 0.

Promenna, ktere drive nebyla prirazena hodnota, ma hodnotu nula. Internim promennym awk se prirazuji hodnoty automaticky (viz dale). Proto napr. program


{ s1 += $1; s2 += $2 }
END { print s1, s2 } 

muze k promenne s1 pricitat. Promenna interpretujici se jako retezec bez prirazene hodnoty obsahuje prazdny retezec.

Potrebujeme-li se ujistit, ze promenna bude chapana jako numericka, pricteme k ni hodnotu 0. Potrebujeme-li naopak promennou interpretovat jako retezec, pripojme k ni prazdny retezec, napr.


b = 12 "" 

I kdyz se numericke promenne zpracovavaji a ukladaji v pohyblive radove carce, desetinna tecka a cislice za ni se vypisuji jenom tehdy, pokud je desetinna cast nenulova. Cislo se na retezec konvertuje podle obsahu promenne CONVFMT volanim sprintf. Retezec se na cislo konvertuje volanim atof.

11.8 Priklad

Na zaver prvni casti pojednani o awk uvedme ilustracni priklad: Chceme awk pouzit na prevod vystupu prikazu ls -l do klasickeho DOSovskeho tvaru vypisu adresare, tj. ze tvaru:

-rw-r--r--   1 simekm staff         173741 May 16 21:10 text2.tex

do tvaru:

text2.tex              173741 May 16 21:10

Sestavime-li kolonu:

ls -l | grep -v ^total | awk -f dirp

potom pro awk (v Systemu V - napr. Solaris, IRIX - pouzijte misto awk program nawk, pokud nemate popisovane gawk) potrebujeme nasledujici program v souboru dirp:

BEGIN {print "User is " ENVIRON["LOGNAME"]; 
       print }
 {printf "%-18s %10i %3s %2i %4s\n", $9, $5, $6, $7, $8;
  suma = suma + $5 }
END {printf "      %4i file(s)%11i bytes\n", NR, suma }

Prikazem grep -v ^total zrusime nevyznamny radek zacinajici slovem total. Pole ENVIRON popiseme v nasledujici casti.

11.9 Regulalni vyrazy

Na miste vzorku se mohou vyskytnout jak zakladni regularni vyrazy tak i rozsirene regularni vyrazy. Regularni vyraz se uzavira do dvojice lomitek. Napr. program

/L.*x/

vypise vsechny radky, ktere obsahuji nejprve znak L a potom x. Hledani vyhovujiciho vzorku muzeme omezit napr. na urcitou polozku. Napr. program

$1 ~ /^[Ll].*x$/ 

vypise ty radky, jejichz prvni polozka zacina pismenem L nebo l a konci pismenem x. Operator !~ vybere ten radek, ktery vyhovujici vzorek neobsahuje.

11.10 Relacni vyrazy

Jazyk awk povoluje pouziti relacnich operatoru <, >, ==, != , >= a <=. Napr. program

$2 > $1 + 99  

vypise ty radky, jejichz druha polozka je alespon o 100 vetsi nez polozka prvni. Aritmeticke operatory se pouzivaji stejne jako v aritmetickych expanzich shellu. Napr. program

NF % 2 == 0 

vypise vsechny radky se sudym poctem polozek. Relacni operatory se mohou pouzivat jak pro aritmeticke srovnavani, tak i pro porovnavani retezcu. Proto napr. program

$1 >= "s"  

vybere ty radky, jejichz prvni polozka zacina znakem s, t, u atd.

11.11 Kombinace vzorků

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 ln 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ý.

11.12 Interval určený vzorky

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.

11.13 Identifikátor položky jako proměnná

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) }

11.14 Příkazy pro řízení toku

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é"
  print
}

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 }

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 #.

11.15 Pole

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 (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"] 

11.16 Funkce

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).

11.17 Interní proměnné awk

11.18 Vstupni a vystupni funkce

Nasleduje souhrnny prehled dosud uvedenych i neuvedenych vstupnich a vystupnich funkci:
close(soubor)
Zavre soubor (nebo presmerovani).

getline
Nacte dalsi zaznam do $0, nastavi se NF, NR, FNR.

getline <soubor
Nacte dalsi zaznam do $0ze souboru soubor, nastavi se NF, NR, FNR.

getline var
Nacte dalsi zaznam do var, nastavi se NF, NR, FNR.

getline var <soubor
Nacte dalsi zaznam do var ze souboru soubor, nastavi se NF, NR, FNR.

next
Ukonci se zpracovavani bezneho zaznamu (radku). Precte se dalsi zaznam a zahaji se provadeni prvniho prikazu programu. Pokud se nacte konec souboru, provede se blok END (je-li nejaky).

next file
Ukonci se zpracovavani aktualne cteneho souboru. Dalsi radek se cte uz z dalsiho souboru. Obnovi se FILENAME, FNR se nastavi na 1. Precte se dalsi radek a zahaji se provadeni prvniho prikazu programu. Pokud se nacte konec souboru, provede se blok END (je-li nejaky).

print
Vytiskne bezny zaznam.

print seznam_vyrazu
Vytiskne uvedeny seznam vyrazu.

print seznam_vyrazu >soubor
Vytiskne uvedeny seznam vyrazu do souboru.

printf format, seznam_vyrazu
Vytiskne uvedeny seznam vyrazu podle zadaneho formatu.

printf format, seznam_vyrazu >soubor
Vytiskne uvedeny seznam vyrazu podle zadaneho formatu do souboru.

system(prikaz_systemu)
Shell provede zadany prikaz_systemu a prevezme se navratovy kod.

11.19 Numericke funkce

V awk muzeme pouzivat nasledujici vestavene aritmeticke funkce.
atan2(y, x)
Vypocte arkustangens y/x a vrati hodnotu v radianech.

cos(vyraz)
Vrati kosinus vyrazu v radianech.

exp(vyraz) Exponencialni funkce.

int(vyraz) Odrizne desetinnou cast.

log(vyraz) Prirozeny logaritmus.

rand() Nahodne cislo mezi 0 a 1.

sin(vyraz) Sinus.

sqrt(vyraz) Druha odmocnina.

srand(vyraz)
Zadany vyraz se pouzije na "rozmichani" generatoru nahodnych cisel. Neni-li vyraz uveden, potom se pouzije aktualni hodnota casu. Funkce vrati predchozi hodnotu vyrazu.

11.20 Retezcove funkce

gsub(r, s, t)
Kazdy podretezec retezce t vyhovujici regularnimu vyrazu r se nahradi retezcem s. Funkce vraci pocet nahrad. Pokud nebyl zadan retezec t, pouzije se $0.

index(s, t)
Vrati index podretezce t v ramci retezce s nebo 0, pokud se podretezec nenasel.

length(s)
Funkce vrati delku retezce s nebo retezce $0, pokud jsme s nezadali.

match(s, r)
Vrati se pozice uvnitr retezce s, od ktere zacina podretezec vyhovujici RE r. Nenajde-li se, vrati se 0. Funkce rovnez nastavuje promenne RSTART a RLENGTH.

split(s, a, r)
Rozdeli retezec s do jednorozmerneho pole a podle RE r. Pokud r nezadame, pouzije se obsah FS. Funkce v retezci najde vsechny vyskyty oddelovace podle r. Tyto vyskyty rozdeli retezec na podretezce a jednotlive podretezce se ulozi do elementu pole a cislovanych od 1. Funkce vrati pocet podretezcu.

sprintf(format, vyrazy)
Funkce vytiskne vyrazy podle zadaneho formatu. Vrati se vysledny retezec.

sub(r, s, t)
Funkce se od gsub() lisi tim, ze se nahradi pouze prvni vyhovujici retezec.

substr(s, i, n)
Funkce vraci n-znakovy podretezec retezce s zacinajici na pozici i. Pokud n vynechame, vezme se zbytek retezce s.

tolower(retezec)
Vraci se retezec se vsemi velkymi pismeny prevedenymi na mala pismena. Jine znaky nez velka pismena zustanou beze zmeny.

toupper(retezec)
Vraci se retezec se vsemi malymi pismeny prevedenymi na velka pismena. Jine znaky nez mala pismena zustanou beze zmeny.

11.21 Casove funkce

Program GNU awk poskytuje moznost doplnovat produkovany text informaci o datu a case.

systime()
Funkce predava aktualni cas v poctu sekund od 1.1.1970 (v POSIX kompatibilnich systemech).

strftime(format, cas)
Funkce zformatuje udaj cas podle zadaneho formatu. Hodnota cas musi byt v takovem tvaru, jaky produkuje systime(). Pokud hodnotu cas vynechame, uplatni se aktualni cas. Retezec format se zadava stejne jako ve stejnojmennem knihovnim podprogramu.

Retezec format funkce strftime() obsahuje jak identifikaci casovych udaju (zacinaji znakem %), tak i normalni text - ten se opise beze zmen. Casove udaje jsou nasledujici (uzivatel by mel mit moznost konfigurovat udaje predavane touto funkci podle narodnich zvyklosti):

Uvedme si priklad:


strftime("Dnes je %d. %m. %Y a mame %H:%M hodin.")

11.22 Retezcove konstanty

Retezcove konstanty uvnitr programu pro awk jsou retezce uzavrene do dvojic uvozovek. Uvnitr techto retezcovych konstant muzeme pouzivat tyto escape posloupnosti:

Vyse uvedene escape posloupnosti se mohou pouzit i uvnitr jednoznakoveho RE reprezentujiciho tridu znaku. Napr. '/[ \t\f\n\r\v]/' vyhovuje vsem znakum typu "bile misto".

11.23 Specialni soubory

GNU verze awk pri presmerovavani vystupu prikazu print, printf a pri cteni pomoci getline interne zpracovava nasledujici specialni soubory. Tyto specialni soubory zprostredkuji pristup k otevrenym popisovacum souboru zdedenych od rodice (zpravidla od shellu) nebo poskytnou informace o procesu.

/dev/pid
Prectenim tohoto souboru obdrzime cislo aktualne beziciho procesu ukoncene znakem noveho radku.

/dev/ppid
Prectenim tohoto souboru obdrzime cislo rodicovskeho procesu.

/dev/pgrpid
Prectenim tohoto souboru ziskame skupinove ID aktualne beziciho procesu.

/dev/user
Prectenim tohoto souboru obdrzime jeden zaznam ukonceny novym radkem. Polozky zaznamu jsou oddeleny mezerou. Polozka $1obsahuje uzivatelske ID z volani getuid(), $2obsahuje uzivatelske ID z volani geteuid(), $3obsahuje ID skupiny z getgid(), $4je hodnota z getegid(). Pripadne dalsi polozky jsou hodnoty vracene volanim getgroups().

/dev/stdin
Standardni vstup.

/dev/stdout
Standardni vystup.

/dev/stderr
Standardni chybovy vystup.

/dev/fd/n
Soubor spojeny s otevrenym popisovacem souboru cislo n.

Vystup na standardni chybovy vystup muzeme poslat napr. timto prikazem:


print "Stala se chyba!" > "/dev/stderr"

11.24 Volby GNU awk

Identifikatory voleb podle POSIX zacinaji jednim znakem minus, volby podle GNU zacinaji dvema minusy. V ramci jedne volby -W lze zadat vice slovnich voleb, stejne tak lze zadat i vice voleb -W na jednom radku.

-Ffs nebo --field-separator=fs
Nastaveni oddelovace polozek na vstupu (tj. urceni implicitni hodnoty promenne FS).

-v promenna=hodnota nebo

--assign=promenna=hodnota
Uvedene promenne se priradi zadana hodnota. Takto nastavene promenne jsou k dispozici jiz behem bloku BEGIN.

-f soubor nebo --file=soubor
Program se bude cist ze zadaneho souboru. Techto voleb muze byt na prikazovem radku vice.

-W compat nebo --compat
Program GNU awk se spusti v rezimu kompatibility s klasickym awk. Vsechna GNU rozsireni jsou vypnuta.

-W copyleft nebo -W copyright nebo --copyleft nebo --copyright
Na standardni chybovy vystup se vypise GNU copyright.

-W help nebo -W usage nebo --help nebo --usage
Na standardni chybovy vystup se vypise kratka napoveda k programu.

-W lint nebo --lint
Program upozorni na ty programove konstrukce, ktere nemuseji jine implementace awk zpracovat.

-W posix nebo --posix
Zapne se kompatibilni rezim s nasledujicimi omezenimi:

-W source=program nebo --source=program
Jako argument teto volby se zadava text programu pro awk. Vyznam spociva v moznosti cist v ramci jednoho spusteni awk program jak ze souboru (napr. knihovnu funkci), tak i z prikazoveho radku (vlastni kratky program). V tomto pripade nelze v ramci volby -W zadat volbu dalsi.

-W version nebo --version
Na standardni chybovy vystup preda informaci o verzi aktualniho awk.

-- Oznamuje konec zadavani voleb.

11.25 Promenna AWKPATH

Do promenne prostredi AWKPATH muzeme obvyklym zpusobem nastavit seznam cest k adresarum, ktere se budou prochazet pri hledani programu (tj. uvedenych za volbou -f). Pokud promenna neexistuje, pouzije se implicitni hodnota:

.:/usr/lib/awk:/usr/local/lib/awk

11.26 GNU awk rozsireni

Na zaver shrneme rozsireni GNU verze awk oproti definici POSIX (viz tez volba -W compat):

11.27 Ilustracni priklady

Mejme textovou databazi predmetu, ze kterych si student pri zapisu do semestru vybira. Jednotlive polozky oddelujeme dvojteckou. Ucitel je v databazi jednoznacne identifikovan svym prihlasovacim jmenem. Pokud je vice nez jeden ucitel, pak jsou jejich prihlasovaci jmena oddelena carkou. Databaze necht ma tento tvar:

P000:3:zk:Architektura pocitacu:brandejs
P004:2:zk:UNIX:brandejs
I011:2:zk:Semantiky programovacich jazyku:
          zlatuska

Ukol zni: vypsat obsah databaze v "citelnem" tvaru a prevest prihlasovaci jmeno na prijmeni a prvni pismeno krestniho jmena. Pro tento ucel si vytvorme napr. soubor logins s nasledujicim obsahem:

adelton:Jan:Pazdziora
brandejs:Michal:Brandejs
kas:Jan:Kasprzak
kron:David:Kostal
zlatuska:Jiri:Zlatuska

Pro prevod prihlasovaciho jmena na prijmeni pak pouzijeme jednorozmerne pole, kde indexem bude prihlasovaci jmeno a obsahem zkonstruovana dvojice prijmeni a krestniho jmena. Pole naplnujeme pouze jednou, a to v casti BEGIN. Databaze predmetu necht se nacita ze standardniho vstupu.

... | awk -F':' 'BEGIN { while ( getline 
<"logins" == 1 ) {
logins[$1]=sprintf("%s %1.1s.", $3, $2) } }
{ pocet=split($5,loginy,",")
for (i=1; i <= pocet; i++) {if (i == 1) 
last = logins[loginy[i]]
else  last = last ", " logins[loginy[i]]; }
printf("%-5s %-50.50s %1s %2s %s\n",$1,$4,
$2,$3,last) }'

Nasledujicim programem spocitame pocet vsech ruznych slov v textu:

BEGIN { FS="[^a-zA-Z]" }
{ for (i=1;i<=NF;i++) words[$i] = "" }
END { delete words[""]   
      # prazdne polozky nepocitame 
      for (i in words) sum++
      print "V textu bylo " sum " ruznych 
             slov"
    }

A dalsi vzorovy program vykonava totez co prikaz wc:

{words+=NF; chars+=1+length($0)}
END {print NR,words,chars}

Tenhle program vymaze vsechny ceckove komentare ze souboru:

{
  if(t=index($0,"/*")) {
     if(t > 1) {
        tmp=substr($0 , 1 , t - 1)
     else
        tmp=""
     u=index(substr($0, t + 2),"*/")
     while(u == 0)
       getline
       t=-1
       u=index($0,"*/")
     }
   if(u <= length($0) - 2)
      $0=tmp substr($0,t + u + 3)
   else
      $0=tmp
   }
  print $0
}


Další Předchozí Obsah