AWK kalba - subtiliau ir daugiau

Kiek anksčiau pristatėme awk kalbą (žr. >>>>> ). Dabar pateiksime naujų aspektų, tačiau prieš tai noriu paminėti pora įdomybių. Dėl visų susitarimų ir detalesnių paaiškinimų – žiūrėkite įvadiniame puslapyje...

1. Visada smalsu, kokia yra trumpiausia kažką realaus daranti programa. Pabandykime tokią:

# maza.awk – labai maža programa
{ }

O dabar pabandykime ją įvykdyti nurodydami kokį nors failą.

awk –f maza.awk test.txt

Programa nepateikia jokių rezultatų. Ar ji tikrai kažką daro? Visų pirma ji nuskaito visą nurodytą failą – eilutė po eilutės. Tačiau kokia iš to nauda? Ogi tas, kad šią programą galima panaudoti patikrinimui, ar failas egzistuoja, o taip pat, jei jis egzistuoja, ar nėra pažeistas. Taigi, ji turi prasmę!

2. Kita įdomus iššūkis – parašyti programą, kuri spausdina savo pačios tekstą. awk tai pasiekiama paprastai – programai pateikiamas pačios programos failas, kurio turinį ji atspausdina. Paprasčiausia tokia programa būtų (pavadinkime ją savipati.awk):

{ print }

Vykdome šią programą nurodydami pačios programos failą – ir ji išveda savo pačios tekstą, t.y.

awk –f savipati.awk savipati.awk
{ print }

Išraiškos

Išraiškas sudaro operatoriais sujungtos konstantos, kintamieji, funkcijos, reguliariuosius išraiškos. Konstantos yra simbolių eilutės arba skaitinės reikšmės. Love AWK cup

Simbolių eilutės yra į kabutes paimtos simbolių sekos, pvz., "Labas, pasauli!". Eilutėse galima panaudoti ir specialias konstrukcijas (angl. escape sequences), kurių populiaresnės yra:
\n – naujos eilutės kodas (\xa);
\r – eilutės pradžios kodas (\xd);
\t – tabuliacijos kodas (\x9);
\xhh - simbolis, kurio šešioliktainė reikšmė nurodyta hh, pvz., \x41 reiškia raidę “A”;
\c – bet koks konkretus simbolis c. Dažniausiai naudojamas „ypatingiems“ simboliams nurodyti, pvz., kabutėms. Pvz., "Sakyk \"Labas!\" "

Kintamasis yra vardas, kuriuo žymima nuoroda į reikšmę. Kintamojo atskiro aprašymo nėra, jo „sukūrimui“ pakanka priskirti reikšmę. Kintamojo varde galima naudoti tik (lotyniškas) raides, skaitmenis ir pabraukimo simbolį ( _ ) – ir jis negali prasidėti skaitmeniu. Beje, awk kalboje didžiosios ir mažosios raidės laikomos skirtingomis, tad kintamieji alga ir Alga yra skirtingi. Kintamiesiems nenurodomas jų tipas – jis atpažįstamas iš konteksto. Kintamojo (arba simbolių eilutės), kurio reikšmė nėra skaitmenys, skaitinė reikšmė yra 0. Pvz., išraiška x = "abc" + 7 kintamajam x priskiria reikšmę 7.

Su objektais (kintamaisiais ir konstantomis) galima atlikti veiksmus. Aritmetiniams veiksmams naudojamo šie operatoriai:
+ - sudėtis;
- - atimtis
* - daugyba;
/ - dalyba;
% - liekana;
^ (arba **) – kėlimas laipsniu.

Eilučių sujungimo operatorius yra tarpas, pvz.,
BEGIN { vardas = "Jonai"; kreipinys = "Labas, " vardas "!"; print kreipinys; }

Programa atspausdins
Labas, Jonai!

Priskyrimo operatoriai

Standartinis priskyrimo operatorius yra =, pvz., x=1;, tačiau awk leidžia tokius "optimizuotus" (C stiliumi) operatorius:
++ - padidinti vienetu;
-- - sumažinti vienetu;
+= - pridėti;
-+ - atimti;
*= - padauginti;
/= - padalinti;
%= - priskirti liekaną;
^= (arba **= )- pakelti laipsniu.

Įdomu, kad ++ ir -- operatorius galima naudoti “iš kairės” ir “iš dešinės” – interpretuojami juos skirtingai. Naudojant “iš dešinės”, pirma paimama (ir panaudojama išraiškoje) objekto (pvz., kintamojo) reikšmė, o tik tada objekto reikšmė pakeičiama (padidinant ar sumažinant vienetu). Naudojant “iš kairės”, pirma pakeičiama reikšmė, o vėliau ši (jau pakeista) naudojama išraiškoje.

Pailiustruosime tai pavyzdžiu:

BEGIN { t=3; x=9; print t++, x+t; 
        t=3; x=9; print --t, (--x)+t; 
      }

Pirmasis print atspausdins 3 ir 13 - spausdinama ankstesnė t reikšmė, t reikšmė padidinama vienetu ir ši naujoji (4) reikšmė panaudoja tolimesniuose skaičiavimuose (x+t). Antrasis print atspausdins 2 ir 10- sumažinama vienetu t reikšmė, tada ji atspausdinama, tada vienetu sumažinama x reikšmė, kuri sudedama su t reikšme (jau sumažinta vienetu anksčiau).

Beje, ++ ir naudojimui yra apribojimų, pvz., jų negalima panaudoti su skaičiais ar išraiškomis (klaidingas užrašas būtų t = 3++; arba x = --(t+5); Apibendrinant, tarkim, x=x+1; galima užrašyti it kitais skirtingais būdais: < CODE>x+=1; x++; ++x;

Palyginimo operatoriai:
< - mažiau;
> - daugiau;
<= - mažiau arba lygu;
>= - daugiau arba lygu;
== - lygu;
!= - nelygu;
~ - tenkina šabloną;
!~ - netenkina šablono;
|| - loginis „arba“;
&& - loginis „ir“;
! = loginis “ne”.

Išvedimas

Išvedimas gali būti nukreiptas į failą arba konvejerį, pvz., print rezultatas > "failo_vardas.txt"
print rezultatas | "komanda"

Pateiksime pavyzdį, išskiriantį visus žodžius tekste ir paskaičiuojantį jų pasikartojimų skaičių:

BEGIN { FS = "[^a-zA-Z+]"; OFS = ": "; 
              print "Žodžių pasiskirstymas faile", ARGV[1] > "pasiskirstymas.txt"; 
} 
{ for (i=1; i <= NF; i++) words[tolower($i)]++; } 
END { for (i in words) print words[i], i > "pasiskirstymas.txt" }

Šablono paėmimas iš komandos eilutės

# sablonas.awk; pirmas parametras panaudojamas kaip šablonas 
BEGIN { sablonas = ARGV[1];  
              # pastumiami komandos eilutės argumentai, kad šablonas nebūtų failo vardu 
              ARGC--; for (i=1; i <= ARGC; i++) ARGV[i] = ARGV[i+1]; 
              if (ARGC == 1) { ARGC = 2; ARGV[1] = "-"; } 
     } 
$0 ~ sablonas { print }

Vykdykime programą, nurodydami, kad reikia pateikti tas teksto eilutes, kuriose yra žodis Jonas:
awk –f sablonas.awk Jonas test.txt

Pastaba: Būtina ne tik paimti argumentą (šabloną), bet ir užtikrinti, kad awk nebandytų jo panaudoti kaip failo, kurį reikia skaityti, vardo.

Formatuotas išvedimas

Kadangi viena pagrindinių awk funkcijų yra pateikti rezultatus (pavadinkime tai ataskaitomis), tai labai svarbu, kad tai galėtume padaryti priimtinu formatu. Todėl greta print yra ir printf , pasiskolintas iš C kalbos. Pirmiausia, jis gali ir paprasčiausiai išvesti teksto eilutę, kaip tai daro print, pvz.,
BEGIN { printf ("Labas, pasauli!\n"); }

Pagrindinis skirtumas tas, kad printf automatiškai neprideda naujos eilutės kodo, kuris identifikuotas kaip „\n“.

printf sintaksė yra
printf (formatuojanti_išraiška [,argumentai])

Beje, skliaustai nėra būtini, - kaip ir argumentai (kaip jų ir nebuvo ankstesniame pavyzdyje).

Formatuojanti išraišką sudaro tekstas, o taip pat formatų specifikatoriai, kurie įvedami procento ženklu (%). Pateiksime pagrindinių specifikatorių sąrašą:
%c – vienas ASCII simbolis;
%d – dešimtainis sveikas skaičius;
%i – dešimtainis sveikas skaičius (papildyta POSIX);
%e – slankaus kablelio skaičius formatu [-]d.trupmeninė_daliselaipsnis;
%E – slankaus kablelio skaičius formatu [-]d.trupmeninė_dalisElaipsnis;
%f – slankaus kablelio skaičius formatu [-]ddd. trupmeninė_dalis;
%g - %e arba %f – tas variantas, kuris trumpesnis;
%G - %E arba %f – tas variantas, kuris trumpesnis;
%o – aštuntainė reikšmė be ženklo;
%s – eilutė;
%x – šešioliktainė reikšmė be ženklo; skaitmenys 10-15 vaizduojami kaip a-f;
%X – šešioliktainė reikšmė be ženklo; skaitmenys 10-15 vaizduojami kaip A-F;
%% - ženklas %.

Be to, printf galima nurodyti išvedamos reikšmės ženklų skaičių bei tikslumą (skaitinėms reikšmėms), o taip pat lygiavimą. Apibendrintas specifikatoriaus formatas būtų
%-plotis.tikslumas specifikatorius ,  pvz.,
BEGIN { printf "|%10s|\n", "Labas!"; }
nurodo, kad reikia išvesti 10 eilutės ženklų, tad pateikiamas rezultatas bus:
|    Labas!|

Bet jei norime pateikiamą tekstą lygiuoti pagal kairę pusę, turime naudoti „-“, t.y.,
BEGIN { printf "|%-10s|\n", "Labas!"; }
pateiksiantį atsakymą:
|Labas!    |

Išsamesniui pavyzdžiui grįškime prie ankstesniame straipsnelyje pateikto pavyzdžio:

# Suskaičiuoti eilutes, žodžius ir simbolius, esančius įvedimo sraute 
function sumuoti (p1, p2) { return p1 + p2 } 
BEGIN { nw = 0; ns = 0 } 
{ nw += NF; ns = sumuoti(ns, length + 1) } 
END { print "Tekste yra", NR, "eilučių,", nw, "žodžių ir", ns, "simbolių" }
>

Jame END { } dalį perrašykime taip:
END { printf ("Tekste yra %d eilučių, %d žodžių ir %d simbolių\n", NR, nw, ns); }

Pabandykite abu variantus ir pastebėkite atsakymų pateikimo skirtumus.

Pastaba: Visi pavyzdžiai buvo išbandyti su GAWK ir MAWK realizacijomis Windows (32 bitų) terpei (nuorodos - atsisiuntimui).

[ vėliau bus pateikta trečia šios (awk) temos dalis ]    

Kelios AWK skirtos knygos:

  1. A.V. Aho, B.W. Kernighan, P.J. Weinberger. The AWK Programming Language, 1988
  2. A. Robbins. Effective awk Programming, 3rd ed., 2001
  3. D. Dougherty, A. Robbins. sed & awk, 2nd ed., 1997
  4. A. Robbins. Effective Awk Programming: A User's Guide for Gnu Awk, 2000

Ankstesnės "Advanced HTML" skyrelio temos:
Unix komandinės eilutė
AWK kalba - sena ir nuolat aktuali
Dygios JavaScript eilutės
Sveikųjų skaičių žaidimai
Pelė uodega švystelėjo...
Pitonas, kandantis sau uodegą
CGI.pm biblioteka: sausainiai
Ką delne mums neša HTML 4.0?
Kaip valdyti piešinių pakrovimo tvarką
Įvadas į Perl kalbą: Kas naudoja Perl?
Kaip lankytoją nukreipti į kitą WWW puslapį
Įlįskite į lankytojų kailį
Kaip sužinoti ekrano charakteristikas?
Vaizdi rašysena - VB Script
Programavimas Unix aplinkoje
ASP patarimų liūnas
Ruby on Rails
JavaScript atspindžiai

JavaScript pradmenys
Tiesa apie REST
Anotacijos Java kalboje
Viešojo rakto kriptografija
Programavimo kalbų klegesys
Java 8: Optional prieš null
Pirmoji programuotoja: Ada Lovelace
ŽODIS – ankstyva lietuviškai prakalbusi programa
Bilas Geitsas: kol dar nebuvo garsus
Lyginant su gimtąja kalba
Kompiuterių ištakos
Vartiklis