Kirjautuminen

Haku

Tehtävät

Joulukalenteri 2009: AWK

Kirjoittaja: trilog (14.12.2009)

AWK on ohjelmointikieli, joka on kehitetty käsittelemään pääsääntöisesti tekstimuotoista tietoa. Se kehitettiin Bell Labs -tutkimus- ja kehitysorganisaatiossa, samassa paikassa on kehitetty myös muun muassa C-ohjelmointikieli, vuonna 1977.

AWK on yksi ensimmäisistä tulkattavista ohjelmointikielistä. Siinä on laajalti käytössä teksti-tietotyyppi, assosiatiiviset taulukot ja säännölliset lausekkeet. Sen syntaksi on hyvin C:n kaltainen, mutta esimerkiksi puolipisteen kanssa ei tarvitse olla niin tarkkana: AWK osaa päätellä myös rivitysten perusteella milloin rivi päättyy. AWK:ssa kaikki tyyppimuunnokset tehdään automaattisesti. Tiedostoja käsitellään joukkona tietueita, jotka erotellaan erottimella (oletuksena rivinvaihto). Myös jokainen tietue erotellaan kentiksi määritetyn erottimen kohdalta (oletuksena välilyönti). AWK-ohjelmissa ei ole rajoitusta käsiteltävien tiedostojen koolle, sillä niitä käsitellään syöttö- ja tulostusvirtojen kautta rivi kerrallaan, joten sillä pystyy käsittelemään helposti myös todella isoja tiedostoja.

AWK:sta on nykyään monia eri toteutuksia. Vuonna 1985 kehitetty GNU:n gawk on nykyään yleisessä käytössä ja se tuleekin muun muassa monessa Linux-jakelussa mukana, siksi tässä esittelyssäkin on keskitytty siihen.

AWK-ohjelma rakenne koostuu yleensä aloitus-, tieto- ja lopetuslohkoista. Tietolohkoja voi olla useampia, joita voidaan määrätä suoritettavaksi tietyin ehdoin.

BEGIN {
    # alkujutut
}

{
    # tämä suoritetaan jokaiselle tekstiriville
}

/regexp/ {
    # tämä suoritettaisiin niille riveille, jossa esiintyy sana "regexp"
}

END {
    # loppuhommat
}

Esimerkki: Tekstin tulostus

Tekstiä voidaan tulostaa käyttäen print-lauseketta tai printf-funkiota tekstin muotoiluun.

BEGIN {
    print "Hyvää joulua";
}

Kuten esimerkistä voi huomata; kaikkia lohkoja ei tarvitse määritellä.

Esimerkki: Fibonaccin luvut

Seuraavassa määritellään funktio, joka tulostaa n -alkiota Fibonaccin lukuja:

# funktiot pitää määritellä lohkojen ulkopuolella
function fib(n) {
    a = 0;
    if (n > 1) {
        b = 1;
        printf("%d %d ", a, b); # C:stä tuttu printf toimii tulostuksen muotoiluun
        for (i = 3; i <= n; i++) {
            c = a + b;
            a = b # huom. ei puolipistettä
            b = c;
            printf("%d ", c);
        }
        print; # print-lauseke, joka tässä tulostaa vain rivinvaihdon
    } else
        print a;
}

BEGIN {
    # tulostetaan 12 ensimmäistä Fibonaccin lukujonon alkiota
    fib(12)
}

Tulostus:

0 1 1 2 3 5 8 13 21 34 55 89

Esimerkki: Säännöllisen tekstitiedoston käsittely

Alla oleva taulukko kuvaa tekstitiedoston rakennetta, johon on kerätty eri henkilöiden kolikkotilanne. Kenttien väliset erottimet ovat sarkaimia.

kenttä 1

kenttä 2

kenttä 3

Mattikulta3
Maijahopea2
Uolevipronssi5
Perttikulta1
Jaskahopea4
Kallekupari2

Seuraavassa ohjelmassa tulostetaan tekstitiedostosta tietoja ruudulle:

BEGIN {
    FS = "\t" # määritellään kenttäerotin sarkaimeksi
    eniten = 0
    lkm = 0
    kolikkohirmu = ""
    arvotaulu["kulta"] = 2.4
    arvotaulu["hopea"] = 1.85
    arvotaulu["pronssi"] = 1.1
}

# kentät pilkotaan automaattisesti ja ne tulevat muuttujiin $1, $2, $3 jne.

{
    printf("Henkilöllä %s on %d %skolikko(a)", $1, $3, $2);
}

eniten < $3 { # pidetään kirjaa siitä, kuka keräsi eniten kolikkoja
    eniten = $3;
    kolikkohirmu = $1;
}

arvotaulu[$2] { # lasketaan vain arvokkaiden kolikkojen arvo (kulta, hopea tai pronssi)
    printf(", joiden arvo on %.2f", arvotaulu[$2]*$3);
    lkm++;
}

{ # tulostetaan vielä jokaisen rivin perään piste ja rivinvaihto
    print ".";
}

END {
    printf("%d henkilöä löysi jonkin arvokkaan kolikon eli ", lkm);

    # seuraavassa lasketaan prosentuaalinen osuus henkilöistä, jotka löysivät jonkin arvokkaan kolikon
    # huomaa esiasetettu muuttuja (NR), joka kertoo tietueiden lukumäärän
    printf("%.2f %% henkilöistä.\n", (lkm/NR)*100);

    printf("Eniten niitä keräsi %s; jopa %d kolikkoa.\n", kolikkohirmu, eniten);
}

Tulostus:

Henkilöllä Matti on 3 kultakolikko(a), joiden arvo on 7.20.
Henkilöllä Maija on 2 hopeakolikko(a), joiden arvo on 3.70.
Henkilöllä Uolevi on 5 pronssikolikko(a), joiden arvo on 5.50.
Henkilöllä Pertti on 1 kultakolikko(a), joiden arvo on 2.40.
Henkilöllä Jaska on 4 hopeakolikko(a), joiden arvo on 7.40.
Henkilöllä Kalle on 2 kuparikolikko(a).
5 henkilöä löysi jonkin arvokkaan kolikon eli 83.33 % henkilöistä.
Eniten niitä keräsi Uolevi; jopa 5 kolikkoa.

Hauska tietää

Linkkejä

Tietoa sivustosta