Awk a proměnné - MujMAC.cz - Apple, Mac OS X, Apple iPod

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:

Seriály

Více seriálů



Informace

Awk a proměnné

31. ledna 2002, 00.00 | Minule jsme se zběžně seznámili se základními vlastnostmi awk; z příkazů, jimž rozumí, jsme však viděli jen nejzákladnější příkaz print. Dnes si ukážeme řadu dalších šikovných triků, které můžeme v awk skriptech používat.

Minule jsme se zběžně seznámili se základními vlastnostmi awk; z příkazů, jimž rozumí, jsme však viděli jen nejzákladnější příkaz print. Dnes si ukážeme řadu dalších šikovných triků, které můžeme v awk skriptech používat.

Ještě pár fint s výběrem řádků

V minulém díku jsme se seznámili s použitím regulárních výrazů: jestliže jsme před skupinu příkazů, umístěnou ve složených závorkách, zapsali regulární výraz mezi lomítky, příkazy se provedly jen nad řádky, jež danému regulárnímu výrazu odpovídají; při použití dvojice regulárních výrazů šlo o řádky počínaje tím, jenž odpovídá prvému výrazu, až po druhý.

Ačkoli kompletní popis všech možností výběru řádků si necháme na konec, ukážeme si dnes ještě dvě velmi šikovné možnosti, které se každou chvíli hodí:

  • zapíšeme-li před skupinu příkazů, zapsaných ve složených závorkách, slovo BEGIN, provedou se tyto příkazy před zpracováním vstupu;
  • podobně pomocí slova END si můžeme vyžádat provedení odpovídajících příkazů až na konci, po zpracování všech řádků textu.

Samozřejmě, že příkazy uvedené BEGIN nebo END nejsou vázány na žádný řádek, a proto v nich nemůžeme používat výrazy $N (přesně řečeno můžeme, ale každý z nich bude representovat jen prázdný textový řetězec). Srovnejte následující příklad s odpovídajícími příklady z minulého dílu:

46 /tmp> ls -l | awk 'BEGIN { print "A jedeme" }
pipe quote> /.gz/ { print $9,"has access rights:",$1 }
pipe quote> END { print "Konec" }'
A jedeme
Kapitola4.tar.gz has access rights: -rw-r--r--
Konec
47 /tmp> 

Mimochodem, chcete-li zadávat dlouhé příkazy "po kouskách", jak ukazuje tento příklad, musíte používat shell sh nebo zsh. Shell tcsh — alespoň se standardním nastavením — by vám jen vynadal "Unmatched '", takže v něm musíte celý příkaz zadat na jediném řádku:

[localhost:/tmp] ocs% ls -l | awk 'BEGIN { print "A jedeme" } /.gz/ { print $9,"has access rights:",$1 } END { print "Konec" }'

To je samozřejmě možné v libovolném shellu.

Proměnné

Skripty awk se podobají programům ve vyšším programovacím jazyce daleko více, než třeba skripty příkazu sed. Můžeme v nich používat příkazy velmi podobné příkazům jazyka C (k tomu se dostaneme zanedlouho), a můžeme v nich používat i proměnné.

Podobně jako v programovacích jazycích, i v awk má proměnná jméno, jež je kombinací písmen, číslic a podtržítek, přičemž nesmí začínat číslicí. Awk ovšem nenabízí bohatství typů, známé z programovacích jazyků: jakákoli proměnná může obsahovat číslo nebo textový řetězec, a awk tyto typy nerozlišuje.

Použijeme-li ve výrazu text jako číslo, pokusí se awk obsah řetězce nebo aspoň několika jeho prvních znaků interpretovat jako desítkově zapsané číslo; pokud se to nepodaří, je hodnota nula. Použijeme-li naopak číslo jako text, prostě se převede na string, obsahující jeho dekadický zápis.

Proměnné také není zapotřebí deklarovat: jakákoli proměnná, již jsme dosud nepoužili, obsahuje prázdný textový řetězec (a jak víme z minulého odstavce, použijeme-li ji v numerických výpočtech, je to totéž, jako kdyby obsahovala nulu).

Nejjednodušší příklad na použití proměnných by mohl vypadat třeba takto:

62 /tmp> ls -l *.tiff
-rw-r--r--  1 ocs  wheel  116880 Jan 23 17:57 BadAspectRatio.tiff
-rw-r--r--  1 ocs  wheel   50114 Jan 23 18:26 Letterbox169.tiff
-rw-r--r--  1 ocs  wheel   29518 Jan 23 17:19 PixelWidth.tiff
63 /tmp> ls -l *.tiff | awk 'BEGIN { min="-" } { print $9,"minuly",min; min=$9 }'
BadAspectRatio.tiff minuly -
Letterbox169.tiff minuly BadAspectRatio.tiff
PixelWidth.tiff minuly Letterbox169.tiff
64 /tmp> 

Samozřejmě, že v praxi nejčastěji využijeme proměnné ve výrazech; těm se však budeme věnovat až příště. Dnes si ještě ukážeme pár dalších zajímavých vlastností samotných proměnných.

Pole

Proměnné v awk mohou reprezentovat jak skalární hodnoty (čísla, textové řetězce), tak i pole hodnot. Pole jsou reprezentována standardním způsobem pomocí hranatých závorek, do nichž se zapisuje index. Jestliže malinko předběhneme a řekneme si, že speciální proměnná NR vždy obsahuje číslo právě zpracovávaného řádku, mohli bychom uložit jména a velikosti všech souborů do polí následujícím jednoduchým skriptem:

{ name[NR]=$9; size[NR]=$5; }

Samozřejmě, aby to mělo dobrý smysl, musel by v témž skriptu být další blok příkazů se specifikací END, ve kterém by se obsah polí nějak zpracoval.

Velmi šikovnou vlastností awk je to, že pole mohou být indexována nejen čísly, ale libovolnými textovými řetězci. Podívejte se na následující příklad; s využitím operátoru '++' pro přičtení jedničky a příkazu for (který si sice popíšeme až později, ale toto jeho použití pro procházení všech prvků pole je snad zcela srozumitelné) spočítáme, kolik souborů v dané složce existuje pro každého uživatele (podívejte se o pár řádků výš, že jméno uživatele je ve výpisu ls -l ve třetím poli):

120 /tmp> ls -l | awk '{ cnt[$3]++ } END { for (i in cnt) print i,cnt[i] }'
root 2
ocs 20
test 4
121 /tmp> 

Vidíme, že dva soubory ve složce patří uživateli "root", dvacet uživateli "ocs" a čtyři uživateli "test".

Příkaz awk sice nepodporuje vícerozměrná pole, ale ve skutečnosti s nimi můžeme bez obtíží pracovat, použijeme-li pro oddělování indexů čárky — asi takto:

{ x[1,NR]=$9; x[2,NR]=$5; }

Jak je to možné? Ale snadno: právě jsme si řekli, že awk podporuje indexování polí libovolným řetězcem; indexy, oddělené čárkou, se prostě spojí do řetězce pomocí vhodného oddělovače (standardně je to netisknutelný znak 034, ale abychom si to mohli dobře znázornit v textu, budeme předpokládat, že jde o podtržítko). Výraz x[9,NR] se tedy na třetím řádku prostě převede na x["9_3"], a je to.

Příště...

...si ještě ukážeme některé standardní proměnné, a pak se už pustíme do výrazů: popíšeme si tedy výše použitý operátor '++' a řadu dalších.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Software  

 

 

 

Nejčtenější články
Nejlépe hodnocené články
Apple kurzy

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: