awk


Obsah:


ce je awk?

Awk je jazyk podobny shellu, ktery je specializovany na praci z textovymi fajly. Je trochu podobny bisonovi/flexovi ale autorovi neslo orychlost ale o snadnost pouziti. Je to opravdu mocny prostredek. Daj se pomoci neho ruzne zpracovavat vystupy ruznych programu. Treba scitat velikosti u ls nebo tak...je celkem sikovny. I kdyz na muj vkus dost zmotany. Ale abych zacal..

Zakladni pouziti

Opravdu jednoduche pouziti awk:
awk '/blb/ { print $0 }' file.txt
Toto bude fungovat trochu jako grep...projde text file.txt a vypise vsechny radky obsaujici blba.. a tad trochu k syntaxi:
cely awk program je prvni parametr..tedy to '/blb/ {print $0 }'
/blb/
je rule...tedy stejne jako u flexu..proste pokud /blb/ plati provede se to za nim
/blb/
napadne pripomina standardni prikaz na hledani /blb, ktery funguje ve vi, more, zless atd.. a presne to dela..jenom na konci je /, aby se dal program psat na jeden radek..tedy /blb/ projde a najde blb..pokud ho najde spusti se to za tim..
{ print $0 }
je ucividne programovy blok, stejny jako v shellu nebo cecku, ktery cosi vypisuje...$0 vypisuje radku..proc to vysvetlim pozdeji.. muzete misto toho psat jenom print..
takze vystup muze vypadat treba:
obravdu blby blbec
blb je blazen 
....
proste radky co obsahuji blb
Je jasne, ze abychom mohli psat neco vetsiho potrebujeme psat vic pravidel a vic radek.. potom se to uz nehodi davat jako parametr a muzeme to napsat treba:
file.awk:
/blb/ { print }
/blazen/ { print }
a ted:
awk -f file.awk file.txt udela:
obravdu blby blbec
blb je blazen
blb je blazen
blazen
...
Tadi vidite ze radka blb je blazen splnuje hned dve rule a tak je taky od obou vypsana..

Rekordy

U awk je kazda radka rekord...rekord je ulozen v promenych $0 az $x podle poctu slov - to jsou fields rekordu...proste jako v shellu parametry programu.. $0 obsahuje cele makro..jako v shellu $* proto print$0 pise celou radku...

Rule v awk je expresion. Expresion v awk nemusi byt jenom /text/ ale fura dalsich veci. Treba:

$5 == "Nov"
Zcela ocividne porovna 5. slovo radky z Nov.. To se hodi treba, kdyz chceme secist vsechny soubory z Novemberu:
$5 == 'Nov' { sum += $4 }
Tady se to trochu komplikuje..vidite ze awk ma v sobe jazyk, ktery umi pracovat z promenyma podobne, jako cecko.. a ted to chce vypsat na konci to se dela pomoci END. To je podminka, ktera plati jenom, kdyz jsme na konci. Tedy:
END { print sum }
je rule, ktera se provede na konci fajlu a vypise soucet..a ted to muzem odpalit:
ls -l | awk -f program.awk
a vypise treba:
54243
Samozdrejme, ze rule END ma i svuj protejsek- BEGIN

Awk scripty

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.

A jde to tuheho

Tak jsem objasnil naproste zaklady awk a ted neco slozitejsiho... nejdulezitejsi promene:
RS
record separator...ten urcuje, jakym znakem se oddeluji rekordy. standardne je to \n tedy nova radka. Pokud treba chcete jako rekord mir normalni vetu date tam '.' atd.. treba:
     BEGIN { RS="." } ; {print}
tento program by mel vypisovat kazdou vetu na novou radku... ; je oddelovac, kdyz nechcete psat na novy radek..takze to za nim je prazdna rule-vzdy true a vypisovani celeho rekordu- tedy od . do .
FS
field separator...to same na oddelovanich jednotlivych polozek rekordu.
OFS
to same ale pro vystup..proste vsechny printy budou necim oddeleny..
$NF
urcuje pocet fieldu v rekordu..kdyz treba chcete zjistit jestli posledni slovo na radce je ahoj date: $NF = ahoj
$0
To jsme tu pouzivali jako cely radek..to ale nemusi byt pravda..
     $1 ~ /foo/ { print $0 }
nebude vypisovat cele radky ale jenom prvni slova, ktera obsahuji foo... ~ je match operator a testuje jestli je string v parametru. Protoze se rule tyka jenom toho prvniho fiedlu je ve $0 jen prvni
$NR
obsauje cislo rekordu...treba program: { print $NR } bude psat 1 2 3 .... pocet radek...proste pro kazdou radku se vyvola ta rule a vypise cislo toho rekordu tedy radky..
FIELDWIDTHS
pomoci teto promene muzete zadat pevne oddeleni fieldu po x znacich. to se hodi treba pri cteni ls nebo jinych programu, kteri maji pevne dane sloupce. treba: FIELDWIDTHS = "9 6 10 7 7 35" nastavi ctecku na vystup programu w kde jsou opravdu takove rozestupy..muzete to prepocitat :)

Co vsechno jde:

muzete pocitat cislo fieldu:
$(2*2)
menit je..
$2 = $2 - 10
a delat dalsi skopiciny... zmena fieldu ovlivni $0 ale neovlivni $NF !

Dalsi jazykove konstrukce

V awk nemusite psat jen rule...ma v sobe opravdu rozsahly programovaci jazyk. muzete psat if..then..else cist dalsi rekord pomoci getline priklad:
{
  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
}
Tak tenhle program vymaze vsechny ceckovsky komentare z fajlu...presto ze je tu hodne veci, o kterych jsem nepsal je jasne ze prvni podminka se snazi na radce najit /* a zjistit jeji pozici do t. Potom pomoci supstr vybrat tu cast, ktera jeste neni v komentari a tu hodit do tmp. Potom vybrat opacnou cast-v komentari a najit */. Pokud se mu to nepovede pracist dalsi radku atd.. a nakonec do $0 ulozit zase tmp-tu neokentarovanou cast a zbytek radky za komentarem.

getline Var
nacte radku do pormene.
getline < FILE
nacte z jineho fajlu
COMMAND | getline normalni pipe...treba:
tmp | getline
spusti program ulozeny v promene tmp a nacte jeho vystup do $0
Pro cteni fajlu pomoci getline se otevre a je treba ho pomoci close zase zavrit!

Vystup

k tomu slouzi print: print statement,statement,statement... bere ceckarsky veci jako \n atd.., ma ceckarsky styl stringu-na vic radek... a je tu OSF promenta...tu jsem uz popsal..urcuje, co se ma tisknout mezi jednotlivyma vystupama... dalsi je OFMT..ta je na rizeni vypisu cisel..muzete tam hodit treba %d, uby to psalo stejne jako ceckarsky printf %d atd...

Dalsi je tu taky kompletni printf.a podporuje veci jako >FILE >>FILE a | Ma taky nekolik special fajlu:

/dev/stderr
/dev/stdout
/dev/stdin
/dev/fd/N   N.kanal...
/dev/ppid parent pid
/dev/pid pid..
/dev/pgrpid
/dev/user
a tak..
v /dev/user je c3elkem slozita syntaxe co v kterym $x je...vyzkousejte si to..

Patterns

typy:
/PATTERN/
vyhledavani..pkud tam text je...je true
EXPRESION
normalni podminka..pokud hodnota je nenulova je pattern true
PAT1,PAT2
vic podminek...pro vic rekordu zaroven...
BEGIN,END
plati jenom na zacatku/konci fajlu
NULL
plati pro VSECHNO

Regular expression

To je na vyhledavani text /TEXT/ muze obsahovat ruzny specialni znake.. takze vyhledavani je chytrejsi/..taky je tu specialni operator ~
exp ~ /text/
ktery hleda text ve vystupu expresiony... a jeho negace:
ecp !~ /text/
specialni znaky:
^
znamena zacatek ..treba: ^ahoj hleda vsechny radky co zacinaji na ahoj
$
znamena konec..
.
znamena jakykoliv znak mimo newline..tedy neco jako ? u souboru
[XYZ]
X,Y nebo Z
[A-Z]
jakykoliv znak od A do Z
[d\]]
znamena d nebo ]....pomoci \ muzeme funkci nejakyho ridiciho znaku vypnout
[]d~]
znamena [ d nebo ~
[^0-9]
vsechno jenom ne cisla!
|
nebo ^P|[0-9]..jakykoliv string co zacina na P nebo obsahuje cisla
(...)
seskupovani a uprednostnovani
*
libovolna posloupnost znaku
+
libovolna nenulova posloupnost
?
znamena ze tam muze ale nemusi ten znak byt fe?d bere fed a fd ale nic dalsiho
\ rusi ucinek specialniho znaku

Dalsi expresions

mame tu taky celou radu oplen normalnich ceckovskych opeartoru a funkci.. jako >,<,== atd... +,-,* atd... muzeme pouzivat tolower na zabraneni case sensitivity i hledani apod..ma maskalackej styl stringu: $1 == "ahoj" neni blbost ale funguje! a taky prazdna podminka NULL se muze vynechacvat a nepsat nic.

Taky mame pole,ceckarsky ridici konstrukce a fura dalsich veci,ktere se mi sem uz nevejdou


Tento soubor je soucasti rozsahle sbirky skolicek na http://www.ucw.cz/~hubicka/skolicky

Take si muzete prohlidnout jeji puvodni textovou podobu

Nebo mi mailnout na hubicka@ucw.cz

Copyright (C) Jan Hubicka 1996