awk
Obsah:
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..
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