Awk
awk je nástroj navržený pro zpracování textových dat, načítaných ze souboru nebo přímo z datového proudu. Jeho název vychází z počátečních iniciál příjmení autorů původní verze - Alfreda V. Aho, Petra J. Weinbergera a Briana W. Kernighana.
Awk, to je zároveň programovací jazyk, který pracuje s řetězci, asociativními poli (kde jsou jednotlivé položky pole indexovány řetězci) a regulárními výrazy.
Awk je jedním z nejstarších unixových nástrojů, zvláště mocným ve spojení s rourami, který se dodnes používá ve všech moderních operačních systémech, vycházejících z Unixu. Nejde však o původní awk, ale jeho klony (i když s původní aplikací se můžete setkat také). Vlastní příkaz awk je tak většinou pouze symbolickým odkazem.
Jiné implementace awk
[editovat | editovat zdroj]Awk byl původně napsán v r.1977 jako součást distribuce UNIX v.7
- nawk
- V r 1985 autoři rozšířili možnosti jeho skriptovacího jazyka a přidali možnost uživatelsky definovat vlastní funkce. Tento skriptovací jazyk byl pak popsán v knize "The AWK Programming Language", vydané r. 1988 a modifikovaná verze programu zahrnuta do distribuce UNIX System V. Aby bylo možno identifikovat tuto inovovanou verzi programu awk, byla nazvána nawk (zkratka z "new awk"). Tato verze pak byla uvolněna k volnému použití r. 1996 a je stále spravována Brianem Kernighanem.
- gawk
- (zkratka z "GNU verze awk") byl napsán jako GNU implementace awku v době kdy ještě nebyl uvolněn. Oproti původnímu awk má navíc např. funkce pro práci s časovým razítkem (timestamp)
- mawk
- je implementace vycházejícího z původního awk vytvořená Mikem Brenanem (název byl vytvořen pravděpodobně přidáním počáteční iniciály jeho jména). Oproti jiným implementacím by měl být rychlejší, díky odlišné práci s regulárními výrazy (více na http://www.root.cz/clanky/regularni-vyrazy-6/). Na druhou stranu však má omezení pokud jde o počet a velikost záznamů.
Existují i implementace pro jiné operační systémy např. stránka
- http://short.stop.home.att.net/freesoft/txtfrmt.htm - obsahuje odkazy na verze awk pro MS Windows/DOS
Jak pracuje awk
[editovat | editovat zdroj]Awk postupně načítá ze vstupního proudu dat jednotlivé řádky, a v nich postupně vyhledává vzorky - znakové řetězce, které mohou být určeny např. regulárními výrazy. Pokud nějaký najde, pak provede s řádkem zadanou akci. Po aplikaci sady vzorků a k nim definovaných akcí, pokračuje awk dalším řádkem.
- Řádek nevyhovující žádnému vzorku awk ignoruje
- Pro každý vzorek je akce vykonávána samostatně, tudíž pro řádek vyhovující více vzorkům může být na výstupu více řádků.
- Pokud není nastaven žádný vzorek, pouze akce, tak jsou zpracovány postupně všechny řádky.
Příkazy lze zadat přímo na řádku, nebo v případě rozsáhlejší sady příkazů pomocí skriptu
- Příklad
user@stroj:~/$ awk /vzorek/ soubor_dat.txt
- V testovém souboru
soubor_dat.txt
jsou vyhledány a na standardní výstup vytištěny řádky, které obsahují řetězec "vzorek". Následující příklad vrátí výsledek totožný, přesto si lze povšimnout několika podstatných detailů:
user@stroj:~/$ awk '/vzorek/ { print $0}' soubor_dat.txt
- V prvním příkladě je vykonána výchozí akce awku pro řádek, který odpovídá vzorku -
print
- V prvním příkladu není užito jednoduchých uvozovek, tudíž se na všechny položky vztahují pravidla o expanzi proměnných, atp.
- Druhý příklad názorně demonstruje použití vzorku a akce
Je-li vyhledávaných vzorků nebo spouštěných akcí více, jsou od sebe odděleny středníkem - ;
user@stroj:~/$ awk '/vzorek/ { print $1};/jiny_vzorek/ { print $2}' soubor_dat.txt
- Slovy
- Najdeš-li na řádku řetězec "vzorek", tak pošli na výstup první položku řádku, dále zkontroluj není-li někde na řádku také řetězec "jiny_vzorek", pokud ano, tak pošli na výstup druhou položku řádku. Není-li na řádku žádný z těchto vzorků, tak pokračuj dalším řádkem
Jelikož je řetězec "vzorek" obsažen i v druhém hledaném řetězci "jiny_vzorek", budou postupně za sebou posílány na výstup obsahy první i druhé položky řádku obsahujícího řetězec "jiny_vzorek"
Jak se awk implicitně dívá na soubor
[editovat | editovat zdroj]První_řádek Druhá_položka Třetí_položka Druhý_řádek Druhá_položka Třetí_položka Třetí_řádek Druhá_položka Třetí_položka
Tak tohle je obsah souboru soubor_dat.txt
. Awk při jeho zpracování dělí proud znaků do záznamů (record) a ty do jednotlivých položek (fields). Jelikož je implicitním oddělovačem záznamů konec řádku, odpovídá zpravidla i obsah záznamu, který zpracovává awk obsahu jednoho řádku. Implicitním oddělovačem položek je bílý znak (mezera nebo tabulátor)
Oddělovače jsou uloženy v proměnných RS (oddělovač záznamů) a FS (oddělovač položek) a změnou obsahu těchto proměnných lze přetypovat i implicitní nastavení. Oddělovač položek lze přetypovat i přímo při spuštění awk volbou -F následovanou novým oddělovačem, který může být tvořen i víceznakovým řetězcem, nebo regulárním výrazem (nezapomeňte však, že je nutno ošetřit znaky které by mohl shell nějakým způsobem interpretovat).
Číslo aktuálně zpracovávaného záznamu (zpravidla řádku) je uloženo v proměnné NR a počet položek (sloupců) zase v proměnné NF. Při zpracovávání obsahu řádku se na jednotlivé položky odkazujeme jejich pořadovým číslem ( $1 - první sloupec, $2 - druhý sloupec,.. pozn: položka $0 obsahuje celý řádek)
- Příklad
user@stroj:~/$ awk '{ print $1}' soubor_dat.txt První_řádek Druhý_řádek Třetí_řádek
Zpracování výstupu
[editovat | editovat zdroj]Při zpracování výstupu lze používat i příkazové konstrukce:
if (podmínka) příkaz else příkaz
user@stroj:~/$ awk '{ if (NR==2) print $2; else print $1}' soubor_dat.txt První_řádek Druhá_položka Třetí_řádek user@stroj:~/$
while (podmínka) příkaz
do příkaz while (podmínka)
for (výraz;výraz;výraz) příkaz
break
continue
next
delete pole[index]
exit výraz
Vzorky
[editovat | editovat zdroj]Relační výrazy
[editovat | editovat zdroj]Kombinace vzorků
[editovat | editovat zdroj]Jednotlivé vzorky lze spojovat logickými operátory && (AND), || (OR) a ! (NOT)
- Příklad
user@stroj:~$ awk '$1 >= "1" && $1 < "T" && $1 !~ /^D.*k$/ {print $0}' soubor_dat.txt První_řádek Druhá_položka Třetí_položka user@stroj:~$
- Výrazu vyhoví pouze ty řádky, jejichž první položka je větší než "1" a zároveň menší než "T" s současně neobsahuje textový řetězec začínající na "D a končící písmenem "k" Pro větší názornost, rozšíříme-li obsah souboru
soubor_dat.txt
- Příklad
user@stroj:~$ cat soubor_dat.txt První_řádek Druhá_položka Třetí_položka Druhý_řádek Druhá_položka Třetí_položka Třetí_řádek Druhá_položka Třetí_položka Čtvrtý_doplňkový_řádek Doplňkový_řádek číslo_pět Dodatečný řádek user@stroj:~$ awk '$1 >= "1" && $1 < "T" && $1 !~ /^D.*k$/ {print $0}' soubor_dat.txt První_řádek Druhá_položka Třetí_položka Dodatečný řádek user@stroj:~$
- Jak vidno výrazu vyhověl rovněž "Dodatečný řádek", protože jeho první položka, řetězec "Dodatečný" sice začíná na "D", ale nekončí na "k"
Intervaly
[editovat | editovat zdroj]BEGIN a END
[editovat | editovat zdroj]Potřebujeme-li aby awk vykonal nějakou akci před vlastním zpracováním proudu dat, nebo po, použijeme klíčového slova BEGIN nebo END. Jde v podstatě o speciální typ vzorků, které ovšem nejsou testovány pro každý záznam, ale naopak, jejich akce jsou spuštěny před začátkem zpracování dat (BEGIN) a jeho skončení (END).
- Příklad
user@stroj:~/$ awk 'BEGIN { print "ještě jsem nezačal.."};END { print "a už jsem skončil.."}' soubor_dat.txt ještě jsem nezačal.. ..a už jsem skončil user@stroj:~/$
Akce
[editovat | editovat zdroj]Jako akce se označuje sekvence příkazů pro awk. Ty se od sebe oddělují buďto prázdnými řádky
awk 'BEGIN{hodnota=0} {hodnota+=$5} END{print hodnota} ' soubor_s_daty
nebo středníky
awk 'BEGIN{hodnota=0};{hodnota+=$5};END{print hodnota}' soubor_s_daty
Proměnné a výrazy
[editovat | editovat zdroj]Jak už naznačuje výše uvedený příklad, awk pracuje také s proměnnými a matematickými výrazy
Funkce
[editovat | editovat zdroj]Volby pro awk
[editovat | editovat zdroj]Použitelné proměnné - shrnutí
[editovat | editovat zdroj]Proměnná | Popis |
---|---|
RS | oddělovač záznamů |
NR | číslo aktuálně zpracovávaného záznamu |
FS | oddělovač položek |
NF | počet položek aktuálního záznamu |
FILENAME | jméno aktuálního vstupního souboru (v případě standardního vstupu "-" |