Ctl160 490160-0 Kolmas luento, 10.2.2003 Nicholas Volk Yleisen kielitieteen laitos, Helsingin yliopisto Ctl160 490160-0Kolmas luento, 10.2.2003 p.1/28
Unohtui viime kerralla... Skriptin ajaminen edellyttää ohjelman suoritusoikeuden lisäksi myös ohjelman lukuoikeuden Konekielisen tiedoston ajamiseen riittää siis pelkkä suoritusoikeus... Nicholas Volk p.2/28
Tällä kerralla Paljon Perliä, toivottavasti ei liikaa Perusohjelmointirakenteet (muuttujat, ehdot ja silmukat), joilta lingvisti ei voi välttyä, jos haluaa tehdä koneella jotain perusfrekvenssilistaa tai -konkordanssia kummempaa... Vähemmän lingvistiikkaa tällä kerralla Nicholas Volk p.3/28
Perl-skriptit Käytettävän Perl-tulkin nimi tulee ensimmäiselle riville #!/usr/bin/perl Perlin tiedostopäätteitä ovat ainakin.perl,.prl,.pl ja.pm Tosin ainakin.pl saattaa viitata myös Prolog-tiedostoon... Emacs saattaa taas tunnistaa käytetyn komentotulkin ja mennä itsekseen Perl-moodiin Tulkin saa päälle käskyllä M-x perl-mode Nicholas Volk p.4/28
Klassikko Erään yleisen ohjelman perl-toteutus (hello.perl): #!/usr/bin/perl print "Hello World!\n"; Luku- ja suoritusoikeuden annon jälkeen ohjelman voi ajaa kutsumalla sitä Käsky print ei ole komentotulkin käsky, eli Perlissä käytetään kielen omia käskyjä, ei komentotulkin käskyjä! Puolipiste ; kertoo Perl-tulkille käskyn loppumisesta Ohjelma koostuu yleensä useammasta peräkkäinen kirjoitetusta käskystä Nicholas Volk p.5/28
Vaihtoehtoinen tapa Skriptiä voi kutsua myös seuraavasti: perl ohjelma Tällöin skripti vaatii vain lukuoikeuden Windowsin MS-DOS-tilassa Perliä käytetään näin! Windows-maailman graafisella puolella ajovaihtoehto olisi kai kertoa, että tietyn päätteen omaavat tiedostot avataan Perl-tulkkia käyttäen, luulisin. Nicholas Volk p.6/28
while while-silmukan sisällä olevat käskyt suoritetaan kunnes ehto on epätosi (eli ei toteudu) Ehto kirjoitetaan tavallisten sulkujen sisään while-käskyt perään Ehton toteutuessa suoritettavat käskyt kirjoitetaan aaltosulkeiden sisään ehdon perään Formaalisti: while ( EHTO ) { käsky 1; käsky 2;... käsky n-1 käsky n; } Nicholas Volk p.7/28
Komentorivimuisteloja Komentorivikäytössä Perlin p-optiohan kertoi, että annetut käskyt tehdään kullekin syöteriville ja lopuksi tulostetaan syöterivi (mahdollisesti muuttuneena) eli Formaalisti p-optio tekee siis seuraavaa: while (<>) { käskyt; } continue { print $_; } continue-käskyä ei kurssilla muualla käytetä Sitä ei siis tarvitse osata, kunhan ymmärtää komentorivikäytön Nicholas Volk p.8/28
Oletusmuuttuja $_ ja timantti <> Perlin muuttujat ovat muotoa $nimi Perlissä on oletusmuuttuja nimeltään $_ Jos mm. s///-käskyissä ei kerrota käytettyä muuttujaa, käytetään oletusmuuttujaa. <> eli timantti lukee yhden rivin (tai oikeammin tietueen) verran syötettä. while-käskyn yhteydessä (ja vain siinä) timantilla luetun rivin arvo talletetaan automaagisesti oletusmuuttujaan timantti yrittää löytää syötteensä ensin komentorivillä kerrottuista tiedostoista jos niitä ei ole, syöte luetaan kantasyötteestä Nicholas Volk p.9/28
cat-käsky Perlillä #!/usr/bin/perl while (<>) { print $_; } # risuaita on kommentti myös Perlissä! Ohjelma lukee rivin syötettä ja tulostaa sen print-käsky on sisennetty, koska sisentäminen helpottaa luettavuutta Ohjelman toimintaan sisentäminen ei vaikuta Nicholas Volk p.10/28
wc -l käsky Perlillä #!/usr/bin/perl $rivit = 0; while (<>) { $rivit = $rivit + 1; } print $rivit. "\n"; Alustetaan muuttuja $rivit alkuarvolla 0 Perlin muuttujat voivat olla samanaikaisesti sekä numeroita että merkkijonoja, eli ei tyyppimuunnoksia Alustamattomat muuttujan numeerinen alkuarvo on 0 ja merkkijonoarvo tyhjä Nicholas Volk p.11/28
wc -l käsky Perlillä #!/usr/bin/perl $rivit = 0; while (<>) { $rivit = $rivit + 1; } print $rivit. "\n"; Jokaisen rivin yhteydessä kasvatetaan $rivit muuttujan arvoa yhdellä Syötteen loputtua tulostetaan muuttujan $rivit arvo eli luettu rivimäärä ja rivinvaihtomerkki. on kaksi merkkijonoa yhteen liittävä katenaatio-operaatio Nicholas Volk p.12/28
Muuttujista Annettaessa muuttujalle arvo, muuttuja kirjoitetaan =-merkin vasemmalle ja annettavan arvon tuottava yhtälö oikealle puolelle: $sata = 15 * 6 + 10; Yhteenlaskun merkki on + ja vähennyslaskun - Kertominen tapahtuu asteriskin * avulla Jakolaskus on sekin tuttu / Nämä riittävät tällä kurssilla, lisäksi on mm. jäännösjako % ja eksponentti ** Nicholas Volk p.13/28
Muuttujista (2) Muuttujien laskemisjärjestys on koulusta tuttu Laskujärjestyksen voi vaikuttaa sulkujen avulla: $sata = 10 + ( 15 * 6); Muuttujilla on sekä numeerinen että merkkijonoarvo eli samaan muuttujaan voi viitata sekä merkkijonona että numerona Merkkijonoille on olemassa katenaatio-operaatio. $x = 100; $y = $x. $x; # nyt $y:n arvo on "100100" Nicholas Volk p.14/28
Muuttujista (3) On olemassa muutama lyhennetty tapa muuttaa muuttujan arvoa ++$muuttuja; ja $muuttuja++; kasvattavat muuttujan arvoa yhdellä --$muuttuja; ja $muuttuja--; vastaavasti vähentävät $muuttuja += 5; kasvattaa muuttujan arvoa viidellä $muuttuja *= $muuttuja; kertoisi muuttujan arvon itsellään $muuttuja.= $muuttuja; aiheuttaisi reduplikaation Nicholas Volk p.15/28
Muuttujista (4) Alustamattoman muuttujan eli muuttujan, jolle ei ole asetettu arvoa, numeerinen arvo on 0 ja merkkijonoarvo (eli tyhjä merkkijono) Alustamaton muuttuja, tyhjä merkkijono ja 0 ovat ehtolausessa epätosia kaikki muut arvot ovat tosia Nicholas Volk p.16/28
Ensimmäinen versio head-käskystä Perlillä #!/usr/bin/perl $rivit = 0; while (<>) { if ( $rivit < 10 ) { print $_; } $rivit++; } while-silmukan ehto <> on tosi, jos syötettä on saatavilla Ehto < on tosi kun oikealla puolella oleva luku on vasemmanpuoleista lukua suurempi eli esimerkin if-ehto voi olla tosi kymmenen kertaa Ehdon ollessa tosi tehdään ehtoa seuraavat aaltosulkeiden rajaamat käskyt Tätä aluetta kutsutaan lohkoksi Nicholas Volk p.17/28
if-käsky Käskyllä if tehdään lohkossa kerrotut käskyt, joss annettu ehto on tosi if-käskyä seuraa 0-n kappaletta elsif-käskyä, joiden ehtoa yritetään toteuttaa, jos mikään aikaisempi ehto ei ole ollut tosi Lopuksi tulee 0 tai 1 else-kohtaa, jotka kertovat mitä tehdä, jos mikään ehto ei ole tosi Aaltosulkeet ovat pakolliset, toisin kuin mm. C:ssä ja Javassa! Nicholas Volk p.18/28
head taasen Aikaisempi versiomme head-käskystä: ei ollut kauhean tehokas: toisin kuin Unixin oma head-käsky, ohjelmamme ei osaa lopettaa saatuaan 10 riviä syötettä. Käskyllä exit voidaan lopettaa ohjelman suoritus #!/usr/bin/perl $rivit = 0; while (<>) { if ( $rivit < 10 ) { print $_; } else { exit; } $rivit++; } Nicholas Volk p.19/28
Murtautuminen ulos silmukasta Käskyllä last poistutaan silmukasta (ei koko ohjelmasta) Head-esimerkissämme olisi exit-käskyn sijasta voinut olla last, sillä silmukan perässä ei ollut muita käskyjä Käskyllä next hypätään silmukan ehtoon ja jätetään käskyä seuraavat käskyt tekemättä. Molempia käytetään yleensä jonkun ehdon toteutuessa Nicholas Volk p.20/28
Matemaattiset ehtotyypit Muutamia keskeisiä matemaattisia ehtoja Yhtäsuuruus: == Erisuuruus:!= Pienempi kuin: < Suurempi kuin: > Muitakin on: Yhtä suuri tai suurempi kuin: >= Yhtä suuri tai pienempi kuin: <= Vertailu <=> esitellään myöhemmin lajittelun yhteydessä (vrt. sort -n) Nicholas Volk p.21/28
Merkkijonoehdot Merkkijonoehdoista keskeisimpiä ovat Yhtäsuuruus: eq Erisuuruus: ne Muitakin on: gt lt le ge cmp Nämä sopivat aakkostamiseen, ainakin cmp esitellään myöhemmin Nicholas Volk p.22/28
Loogiset opeaatiot: negaatio Negaatio muuttaa toden epätodeksi ja päin vastoin Negaation tunnus on Perlissä huutomerkki! Seuraavat ehdot tarkoittavat samaa:! $sana eq "kissa" $sana ne "kissa" Vastaavasti:! $sana ne "kissa" $sana eq "kissa" Eli tuplanegaatio kumoaa itsensä Nicholas Volk p.23/28
Loogiset operaattorit: JA JA-operaation vaatii että sen molemmilla puolilla olevat ehdot ovat tosia Sen tunnus Perlissä on && Koiran määritelmä voisi olla: $karvainen && $haukkuu && $jalkoja == 4 Eli muuttuja itsessään on tosi, jos sen numeerinen arvo ei ole 0 ja merkkijonoarvo ei ole Lienee kuitenkin intuisiivisempaa kirjoittaa $muuttuja!= 0 kuin pelkästään $muuttuja Nicholas Volk p.24/28
Loogiset operaattorit: TAI TAI-operaatio vaatii, että ainakin toinen sen ympärillä olevista ehdoista on tosi Se ei siis vastaa luonnolisen kielen tai-sanaa Operaation tunnus Perlissä on JA suoritetaan ennen TAI-operaatioita Samoin kuin yhtälöiden, myös eri ehtojen käsittelyjärjestykseen voi vaikuttaa sulkujen avulla Ei anneta tämän pelottaa: operaatioita ei joudu tällä kurssilla ihmeemmin yhdistelmään Nicholas Volk p.25/28
Sidontaoperaatiot Myös säännöllisiä lausekkeita käyttää ehtoissa: if ( $sana = /a/i ) { print "Osuma!"; } Edelliset käskyt tulostaisivat Osuma!, jos muuttujassa $sana olisi A- tai a-kirjain (i-optio) Notaatiota = kutsutaan sidontaoperaatioksi Sen vastakohta on! Säännöllisen lausekkeen sisällö voi käyttää muuttujia: $c = "a"; if ( $sana = /$c/ ){print "Osuma!";} Nicholas Volk p.26/28
Sidontaoperaatiot (2) Viime kerralla oli s///:n yhteydestä puhetta muuttujista $1.. $9 Suluilla rajatut muuttujat ovat itse asioissa päällä seuraavaan säännölliseen lausekkeeseen asti Ko. muuttujille ei voi itse antaa uusia arvoja, jolloin saavat uudet arvot #!/usr/bin/perl $merkkijono = "The paths of glory lead but to the grave."; $merkkijono = /(o.*o).*(e.*e)/; print "1: $1\n" print "2: $2\n"; Tulostaisi 1: of glory lead but to 2: e grave Nicholas Volk p.27/28
Sidontaoperaatiot ja oletusmuuttuja Jos jätetään käytetyn muuttujan nimi ja sidontooperaatio pois käskyissä //, s/// ja tr/// viitataan sidontaoperaatioon Niinpä seuraavat tarkoittavat samaa: s/[.:!?]//g; $_ = s/[.:!?]//g; Nicholas Volk p.28/28