760 likes | 904 Vues
PERL. Összeállította: Kosztyán Zsolt Tibor kzst@vision.vein.hu. A PERL alapjai.
E N D
PERL Összeállította: Kosztyán Zsolt Tibor kzst@vision.vein.hu
A PERL alapjai • A Perl programnyelv alkotója, Larry Wall eredetileg rendszeradminisztrációs feladatokra szánta, de mára rengeteget fejlődött, szinte mindenre használható. Egy interpretált nyelvről van szó, mely annyit takar, hogy a "gép nyelvére" való fordítás futtatási időben történik. Fordító szinte az összes platformra létezik, legyen az Unix, Windows, Mac, stb. További előny, hogy ellentétben más programnyelvekkel, a „teljes” Perl ingyenes, szabadon letölthető a Perl weboldalról: http://www.perl.com/. A nyelv tanulása egyszerű, és gyorsan megy, különösen, ha már ismersz más nyelve(ke)t is. Talán épp ezért olyan elterjedt, hiszen az interaktív, CGI-ket használó weboldalak nagy részét Perl-el készítették.
Helló világ! • Talán kezdjük is el, nézzünk meg egy minimális programot, amely a "Helló világ!" szöveget írja ki: print "Helló világ!\n"; #kiírja, hogy Helló világ! • A programot futtatva kiíródik az üzenet. A fenti egy sorról már sok mindenre lehet következtetni. Mint látható, a kiírás a print utasítással történik. A C-hez hasonlóan a szövegek nem tartalmaznak sortörés karaktert, ezt nekünk kell kitenni, a \n szolgálja ezt a szerepet. A sort (mindig) pontosvessző zárja, ez kötelező. Kommenteket #-al írhatunk, a # után következő karaktereket a Perl nem értelmezi.
Adattípusok • A Perl nyelv 5 adattípust ismer, ezek közül most néggyel fogunk részletesebben foglalkozni. Mindegyik típus külön azonosító jellel rendelkezik. Ezek a következők: • Skalár változó ($) - egyszerű sztring, vagy szám • Tömb (@) - tömb (több skalár), számmal indexelve (0-tól indul) • Hash (%) - tömb, sztringgel indexelve (kulcs-érték párok) Szubrutin (&) - egy szubrutint (alprogramot) hív meg • Globális (*) - bármely ugyanolyan nevű adattípusra hivatkozik • A változó nevének első karaktere határozza meg annak típusát. Nézzünk néhány példát: • $valtozo #egyszerű, skalár változó • $tomb[3] #tomb nevű tömb 4. elemére való hivatkozás (a számozás 0-tól indul) • @tomb #tomb nevű tömb egésze • $sash{'kulcs'} #sash nevű, sash kulcs indexű értéke • %sash #sash nevű sash egésze
Változók • A változók típusoktól függően külön tárolódnak, ergo két különböző típusú változónak lehet ugyanaz a neve. Például. az $valami[0] a @valami első eleme, nem az $valami skalár. • Skalár változók A skalár adattípus egyszerű szám vagy sztring (karaktersorozat) tárolására alkalmas, nevét egy $-nak kell megelőznie. Értékadáshoz az értékadó operátort használjuk, egy egyenlőségjelet (=) - az operátorokról később lesz szó. Nézzünk meg egy egyszerű példát: • $nev = "Kiss István"; $kor = 35; • Itt a $nev változó a Kiss István értéket kapta, a $kor pedig a 35-öt. Mint látható, sztring esetén idézőjelet kell használni, ez számnál elhagyható. A sorvégi pontosvessző kötelező!
Változók • Egy változóhoz hozzárendelhetjük egy másik változó értékét is: • $evszam = 1990; $szam = $evszam; #$szám érteke 1990 lesz • Szövegek összefűzése az alábbi módon történik: • $valami = "x"."y"; #$valami érteke xy lesz. • Skalár változók felhasználhatók sztringen belül is, ekkor a változó beszúrását a Perl végrehajtja: • $nev = "Minta Péter"; $udvozlet = "Helló, én $nev vagyok."; • Ekkor a $udvozlet tartalma "Helló, én Minta Péter vagyok." lesz (idézőjelek nélkül természetesen).
Változók • Nézzünk meg egy érdekesebb példát! • $nev = "Minta Péter"; • $udvozlet = 'Helló, én $nev vagyok.\n'; print $udvozlet; • A képernyőre a következő szöveg kerül kiírásra: Helló, én $nev vagyok.\n De miért? Az ok a használt idézőjelekben keresendő. Ugyanis mint látható, itt nem kettős (") idézőjelet használtam, csak szimplát. A Perl a sztringen belüli beszúrást csak " használata esetén végzi el. Itt ejtenék szót az általános levédő karakterről is, mely használatával " idézőjelek között is lehetséges a változóbeszúrás elkerülése. Például: • $nev = "Minta Péter"; $szoveg = "Az \$nev változó tartalma: $nev"; print $szoveg; • A fenti kódrész ezt írja ki: Az $nev változó tartalma: Minta Péter • Ha a levédő karaktert szeretnénk kiíratni, akkor önmagát kell önmagával levédeni, azaz: \\
Tömbök • Egy tömbben több skalár tárolására van lehetőségünk. Ez az egyik legalapvetőbb adatstruktúra, minden nyelvben megtalálható. A Perl-ben a tömbök kezelése dinamikus, mely azt jelenti, hogy ellentétben más nyelvekkel automatikusan kapják a méretüket, és ez automatikusan nő illetve csökken. A tömb nevét @ előzi meg. Létrehozáskor zárójelek között kell felsorolni az elemeket, az alábbi módon: @allatok = ("kutya","cica","madár","csiga","hal"); • Egy allatok nevű tömböt hoztunk létre, mely 5 elemet tartalmaz. Az elemeknél lehetőség van skalárok, vagy tömbök beszúrására is, nézzünk erre is egy példát! • $allat = "viziló"; @madarak = ("papagáj","veréb","kakukk","strucc"); @allatok = ("kecske",$allat,„őz",@madarak,"egér"); • A fenti példában először egy $allat változót hoztunk létre, mely a viziló értéket kapta. Aztán egy @madarak tömb következett, melyben madarakat soroltunk fel. Végül egy @allatok tömböt készítettünk, mely megkapta az $allat, és a @madarak tartalmát is, és még néhány elemet. Ezzel a @allatok tartalma a következő lett: kecske, víziló, őz, papagáj, veréb, kakukk, strucc, egér
Tömbök • Most nézzük meg, hogyan hivatkozhatunk a tömb egyes elemeire! • @evszakok = ("tavasz","nyár",„ősz","tél"); print "A \@evszakok tömb első eleme: $evszakok[0]."; • A program kiírja: A @evszakok tömb első eleme: tavasz. Mint látod, az elemek számozása nullától indul, erre oda kell figyelni! Ezzel a formával tömbök létrehozása, illetve már létező tömbök elemeinek megváltoztatása is lehetséges: • @evszakok = ("tavasz","nyár","nyár","tél"); print "A \@evszakok tömb harmadik eleme: $evszakok[2].\n"; $evszakok[2] = „ősz"; print "A \@evszakok tömb harmadik eleme: $evszakok[2]."; A fenti kódsor először a @evszakok tömb 3. elemének a nyár-t nevezi meg, majd a megváltoztatás után az ősz-t.
Tömbök • Ha a tömböt egy skalárhoz rendeljük hozzá, akkor az a tömb hosszát (az elemek számát) kapja értékül. Például: • @szinek = ("piros","kék","zöld","sárga"); $hossz = @szinek; print $hossz; • A program kiír egy 4-est, mivel létrehoztunk egy @szinek tömböt, mely négy sztringet tartalmazott, majd a $hossz értékének a @szinek -et adtuk meg, így az $hossz a tömb elemeinek számát, a 4-est kapta értékül, mely a következő sorban kiírásra került. Lehetőségünk nyílik u.n. tömbszeletek kezelésére is, ezzel a tömbnek egy részére hivatkozhatunk, az alábbi módon: • @szinek = ("piros","kék","zöld","sárga"); $szelet = @szinek[2,3]; print $szelet; • Ekkor kiírásra kerül, hogy zöldsárga, mivel ez volt a tömb 3. és 4. eleme. Ezzel könnyedén felcserélhetünk két tömbelemet, nem kell külön skalár változót bevonni, amiben ideiglenesen tárolásra kerülne az egyik elem, az egész egy sorral megoldható: • @szinek[1,2] = @szinek[2,1];
Push, pop, shift, unshift operátor • Segítségükkel a tömb végét alakíthatjuk anélkül, hogy tudnánk a tömb hosszát. A push használatával a tömb végéhez lehet csatolni további eleme(ke)t, a pop épp ezzel ellentétes, a tömb utolsó elemét lehet vele eltávolítani. Nézzünk erre egy példát! • @szinek = ("piros","kék","zöld","sárga"); $szin = "lila"; push(@szinek,$szin,"narancs$szinek[3]"); $utolsoszin = pop(@szinek); • Először létrehoztunk egy négyelemű tömböt (@szinek), majd egy skalárt ($szin), melynek a lila értéket adtuk. Aztán a @szinek-hez hozzácsatoltuk a $szin-t, és még egy sztringet, mely a narancs, és a @szinek tömb 4. elemének az összetételéből következett, azaz a narancsból, és a sárgából. Itt is használható egyszerű skalár éppúgy, mint sztring, vagy akár ezek kombinációja. Tehát ekkor a tömbünk elemei a következők: piros, kék, zöld, sárga, lila, narancssárga. Végül a tömb utolsó elemét levágjuk, és egy változóban tároljuk.
Revese • A reverse használatával a tömb elemeinek sorrendjét felcserélhetjük. Ez az operátor nem írja felül az eredeti tömböt, ezért egy másikat kell létrehozni, amely ugyan azokat az elemeket fogja tartalmazni, mint az eredeti, csak fordított sorrendben (hivatkozhatunk az eredeti tömbre is, ekkor felülírja). Lássunk erre is egy példát! • @szamok = (1,2,3,4,5); @visszafele = reverse(@szamok); • Ekkor a @visszafele elemei a következők lesznek: 5, 4, 3, 2, 1. Ha számokból álló tömböt hozunk létre, ezzel lerövidíthetjük a létrehozást: • @szamok = (1..5); • Ezzel ugyan azt értük el, mint a fenti formával, azaz a tömb elemei a következők lettek: 1, 2, 3, 4, 5. Ez használható betűknél is (a-z).
Sort • Ezzel egy tömb tartalmát rendezhetjük: • @szinek = ("piros","kék","zöld","sárga"); @szinek = sort(@szinek); • Mint látható, ez sem írja felül az eredeti tömböt, így ha felül szeretnénk írni, akkor önmagára kell hivatkoznunk. A sort hatására a @szinek tartalma a következő lett: kék, piros, sárga, zöld. • @szamok = (12,5,437,9,28); @szamok = sort(@szamok); • Ekkor a @szamok tartalma: 12, 28, 437, 5, 9. De vajon miért? Mert a rendezés karakterenként történik, a számokat ugyanúgy rendezi, mintha szöveg lenne, azaz először az első számjegy alapján állítja őket sorrendbe, majd ha van egyező, azoknál kezdi el vizsgálni a második számjegyet.
Hash • A hash (más néven asszociatív tömb) abban hasonlít a fent tárgyalt tömbhöz, hogy ebben is skalárok tárolására van lehetőség, azonban itt az indexelés nem számokkal, hanem sztringekkel történik, azaz itt egy tömbelemre nem a száma, hanem a neve szerint hivatkozunk (tehát létrehozáskor ezt is meg kell adni). Nézzünk egy példát hash létrehozására! %sokminden = ("szín","piros","hónap","június","virág","rózsa"); • Ez így elég nehezen nyomon követhető, ezért van egy másik forma is, a magyarázat előtt nézzük meg azt: • %sokminden = ( "szin" => "piros", "honap" => "június", "virag" => "rózsa" ); • Tehát, mint látható, létrehoztunk egy %sokminden nevű asszociatív tömböt, melynek három elemet adtunk: szín, hónap, virág, és ezeknek adtunk értéket is, piros, június, rózsa. Az egyes elemekre való hivatkozás itt is egyszerű skalárként történik, a kívánt elem nevének kapcsos zárójelbe való írásával: • print $sokminden{"honap"}; • A program kiírja, hogy június, mivel fent ezt adtuk meg.
Hash • Természetesen ez a forma használható új tömb létrehozására, már meglévő elemek módosítására, és új elem behozatalára is: • %sokminden = ( "szin" => "piros", "honap" => "június" ); $allatok{"madar"} = "papagáj"; $allatok{"kutya"} = "huski"; $nev = "madar"; $sokminden{"kutya"} = $allatok{"kutya"}; $sokminden{$nev} = $allatok{"madar"}; $sokminden{"szin"} = "sárga"; • Először létrehoztunk egy %sokminden nevű tömböt, mely két elemet kapott, a szin-t és a honap-ot. Aztán egy %allatok tömb került létrehozásra, azonban ez a hivatkozási formával, először kapott egy madar, majd egy kutya elemet. Aztán létrehoztunk egy egyszerű skalárt ($nev). Ez után a %sokminden tömbhöz létrehoztunk egy új elemet, melynek a neve kutya lett, ehhez rendeltük értéknek a %allatok tömb kutya nevű értékét. Aztán a %sokminden-t újabb elemmel bővítettük, melynek neve az $nev változó tartalma lett, értéke pedig a %allatok tömb madar értéke lett. Végül a %sokminden szin nevű paraméterét változtattuk meg sárgá-ra. Tehát a %sokminden tartalma most: szin=>sárga, honap=>június, kutya=>huski, madar=>papagáj.
Keys • Ennek használatával a tömbben lévő kulcsokat kaphatjuk meg. Itt egy példa: • %sokminden = ( "virag" => "rózsa", "szin" => "piros", "honap" => "június");print keys(%sokminden); • Kiírja, hogy viragszinhonap. Ennek később, a ciklusoknál fogjuk sok hasznát venni, ha egy hash összes elemén végig akarunk menni. Ha a keys operátort hozzárendelésnél használjuk, akkor a kulcsok számát adja vissza: • %sokminden = ( "szin" => "piros", "honap" => "június", "virag" => "rózsa" ); $hossz = keys(%sokminden); print $hossz; #kiírja, hogy 3
Values • A values operátor hasonló, csak ez nem a kulcsokat, hanem az értékeket adja vissza: • %sokminden = ( "virag" => "rózsa", "szin" => "piros", "honap" => "június" ); print values(%sokminden); • Kiíródik a következő karaktersorozat: rózsapirosjúnius. A hozzárendelést egy tömbhöz is végezhetjük: • %sokminden = ( "virag" => "rózsa", "szin" => "piros", "honap" => "június" ); @ertekek = values(%sokminden); print $ertekek[1]; • Mint látható, az értékeket egy tömbben tároltuk, majd kiírattuk a tömb második elemét, azaz a június-t.
Delete • A delete operátor, meglepő módon törlésre használható: • %sokminden = ( "virag" => "rózsa", "szin" => "piros", "honap" => "június" ); delete $sokminden{honap}; • %sokminden tartalma: virag=>rózsa, szin=>piros lesz.
Szubrutinok • Az alprogramok jele a &, tehát meghívásnál ezt kell alkalmazni. Deklarációnál (tehát ott, ahol leírjuk, hogy mit is csináljon a szubrutin) a sub-ot kell használni. • &alma; exit; sub alma { print "Ezt az üzenetet az alma nevű szubrutin írta ki."; } • Mint látható, először meghívtuk az alprogramot. Aztán egy exit utasítás következett, ez a programból való kilépésre, vagy a program megszakítására szolgál. Aztán következett maga a deklaráció, melyet egy sub utasítás kiadásával lehet elkezdeni, ezt az alprogram neve (ahogy hivatkoztunk rá) követi, majd egy utasításblokk, Tehát egy { majd az utasítások felsorolása, végül egy }. Ilyen utasításblokkokat még sok helyen fogunk használni. A blokkon belül nem szükséges a sorok elé szóközöket vagy tabulátorokat tenni, ez csak az áttekinthetőséget javítja (hosszabb programok esetén érdemes használni).
Szubrutinok • Alprogramoknál használatos a return utasítás, mellyel visszatérési értéket adhatunk meg: • $udvozlet = &alma; print "$udvozlet\n"; exit; sub alma { $szoveg = "Helló!"; return $szoveg; } • Itt az alma szubrutinban egy $szoveg változóba tároltunk egy sztringet, a hivatkozáskor pedig az egész alprogramot egy változóhoz rendeltük hozzá, majd kiírattuk. Természetesen lehetőség van adatok átvitelére is, ezeket a hivatkozáskor kell megadni, majd az alprogramban a @_tömb elemeiként kapjuk meg őket: • &udvozlet("Helló","Minta Péter"); exit; sub udvozlet { print "$_[0], az én nevem $_[1].\n"; } • A hivatkozásnál két paramétert adtunk meg, két sztringet. Az alprogramban pedig a két adat felhasználásával egy üdvözlő szöveget írtunk ki, feltételezve, hogy az első adat egy köszönési forma, a második pedig egy név.
Szubrutinok • @elemek = ("könyv","telefon","internet","magazin"); &utolso(@elemek); exit; sub utolso { $utolso = pop; print "Az utolsó elem: $utolso\n"; } • A program kiírja, hogy magazin. De miért? Először létrehoztunk egy tömböt (@elemek), majd hivatkoztunk az alprogramra, a @elemek tömb tagjait megadva paraméterként. A szubrutinban pedig egy változóban tároltuk az átadott elemeket tartalmazó tömb utolsó elemét. Ami érdekes, hogy a @_ nevet meg sem említettük, a pop operátort paraméter nélkül használtuk. Ez azért van, mert mindig az _ nevű adattípus az alapértelmezett, tehát ha valahol nem adok meg semmit, akkor ezt fogja használni.
Értékadó/aritmikai operátorok • $szam = 10; $szam += 4; #$szam értéke 14 lesz $szam -= 5; #$szam értéke 9 lesz $szam *= 2; #$szam értéke 18 lesz $szam /= 3; #$szam értéke 6 lesz $szam .= " db alma"; • Amint látható, egy $szam változót hoztunk létre, majd különböző műveleteket hajtottunk vele végre.
Értékadó/aritmikai operátorok • $a = 10; $b = 2; $c = $a * $b; #$c értéke 20 $d = 2 * 5; #$d értéke 10 $d += $b * $c; #$d értéke növekszik (2*20) –al, tehát 50 lesz print $d - $b; #kiírja, hogy 48 • Mint látható, létrehoztunk két változót, majd egy harmadikba a kettőt összeszoroztuk. Aztán egy negyedik változóba két számot szoroztunk össze, utána pedig növeltük az értékét az első két szám szorzatával, végül levontuk belőle $b értékét, és az eredményt kiírtuk. Utóbbi két műveletet egy sorban is el lehet végezni.
Értékadó/aritmikai operátorok • Most pedig nézzünk meg még két operátort, a maradékképzőt és a négyzetre emelőt: • print 10 % 3; #kiírja, hogy 1 print 8 % 3; #kiírja, hogy 2 print 2**2; #kiírja, hogy 4 print 5**2; #kiírja, hogy 25 • Mint látja, a % operátor maradékot képez, hatványozásra pedig a ** szolgál. Most nézzünk meg egy érdekesebb példát! • print -4 ** 2; #kiírja, hogy -16 • Ez vajon hogy lehet, hiszen –4 a négyzeten, az 16? – vetődik fel a kérdés. A válasz egyszerű, a Perl a hatványozást magasabb rendű műveletként kezeli, ezért előbb elvégzi, és utána teszi ki az előjelet.
Aritmikai operátorok • $x = -4; print $x**2; #kiírja, hogy 16 • Itt először eltároltuk a negatív számot egy változóba, majd a változót hatványoztuk, a kimenetre így már 16 kerül. A Perl külön operátorokkal rendelkezik az inkrementáláshoz és a dekrementáláshoz, ez a ++ és a --. Mindkettő tehető a változó elé és mögé is, a különbség az, hogy ha a változó előtt van, akkor az értéket előbb növeli/csökkenti, és a visszatérési érték már az új érték lesz, viszont ha a változó mögött van, akkor a visszatérési érték az eredeti érték lesz, és csak ez után fogja növelni az értéket. Nézzünk egy példát! • $a = 1; $b = ++$a; print "\$a értéke: $a\n\$b értéke: $b\n"; • A kimenetre ez kerül: • $a értéke: 2 $b értéke: 2
Aritmikai operátorok • Most nézzük meg ugyanezt, ha a ++ a változó mögött van: • $a = 1; $b = $a++; print "\$a értéke: $a\n\$b értéke: $b\n"; • A kimenetre ez kerül: • $a értéke: 2 $b értéke: 1 • A különbség egyértelmu, az elso példában az $a értékét eloször növelte, ezért a visszatérési érték már 2, a másodikban viszont csak utána, ezért a visszatérési érték még 1 volt. Ugyan ez a helyzet a -- -nál is.
Aritmikai operátorok • Az ismétlő operátor (x) egy sztringet sokszoroz meg az alábbi módon: • print "-" x 10; #kiírja, hogy ---------- • Az ismétlés operátorral tömböket is hozhatunk létre, ekkor zárójelekkel kell ezt jelölni: • @tomb = ("-") x 5; print $tomb[2]; • Itt egy 5 elemu tömb került létrehozásra, melynek minden eleme egy - karakter, majd kiírtuk a tömb 3. elemét.
Összehasonlító operátorok • > (nagyobb, mint) < (kisebb, mint) >= (nagyobb vagy egyenlő) <= (kisebb, vagy egyenlő) != (nem egyenlő) <=> (összehasonlítás) • Amikor két adatot összehasonlítunk, és az összehasonlítás igaz, akkor a Perl egy 1-est fog visszaadni, ha nem igaz, akkor nullsztringet. Kivétel az összehasonlítás, ahol ha nagyobb, akkor 1-et ad vissza, ha kisebb, akkor –1-et, ha egyenlő, akkor 0-át. Tekintsünk meg néhány példát! • $igaz = (4 != 3); $hamis = (10 < 10); print $igaz; #kimenet: 1 print $hamis; #nincs kimenet print (2 > 1); #kimenet: 1 print (4 <= 4); #kimenet: 1 print (1 >= 3); #nincs kimenet print (4 <=> 3); #kimenet: 1 print (4 <=> 4); #kimenet: 0 print (4 <=> 5); #kimenet: -1
Összehasonlító operátorok • A összehasonlító operátoroknak létezik egy másik változata is, melyet sztringek összehasonlításánál használunk: • eq (egyenlő) ne (nem egyenlő) gt (nagyobb, mint) lt (kisebb, mint) ge (nagyobb, vagy egyenlő) le (kisebb vagy egyenlő) cmp (összehasonlítás)
Logikai operátorok • and, or, not - &&, ||, ! aki már jártasabb egy kicsit ezen a téren, az már biztosan találkozott velük. Több kifejezést lehet segítségükkel vizsgálni, az and akkor tér vissza igaz értékkel, ha mindkét feltétel igaz, az or a bal oldalival ha igaz, ha nem, akkor a jobbal, a not pedig igazzal tér vissza, ha mindkét kifejezés hamis: • print (5 > 1) && (10 > 9); #kimenet: 0 • A kimenet 0, vagyis true, mert mindkét állítás igaz. Viszont az alábbi példa már nem fog kiírni semmit (false): • print (5 < 1) && (10 > 9); #kimenet: 1 • Mint látható, az && operátornál elég, ha csak az egyik kifejezés hamis, a visszatérési érték már false lesz.
Vezérlési szerkezetek, elágazások • A vezérlési szerkezetek általában egy feltételből, és egy utasításblokkból állnak. A feltétel feladata, hogy az utasításblokkot a feltétel logikai értékének megfelelően hajtsa végre. Mi is az az utasításblokk? Egy { és } –el elhatárolt programrész, melyekben tetszőleges számú utasítás található. Az egyik leggyakrabban használt vezérlési szerkezet az if/elseif/else. Nézzünk egy egyszerű példát az if használatára! • $a = 1; $b = 3; if ($a < $b) { print 'Az $a változó értéke nagyobb, mint az $b-é.'; } • Két skalár került létrehozásra ($a, $b), majd egy elágazás következett, melyben megvizsgáltuk, hogy az $a értéke nagyobb-e, mint az $b értéke, és ha ez igaz volt, akkor kiírattunk egy sztriget. Nézzük meg a fenti példát az else utasítással kibővítve. Az else után következő utasításblokk akkor hajtódik végre, ha az if után következő feltétel nem igaz. • $a = 1; $b = 3; if ($a == $b) { print 'Az $a változó értéke egyenlő az $b-ével.'; } else { print 'A feltétel nem igaz!!'; }
Elágazások • Mivel nem egyenlők, “A feltétel nem igaz" sztring került kiírásra. Az if-nek az else-en kívül van még egy párja, az elseif mely az else-hez hasonlóan akkor hajtódik végre, ha az if nem igaz, viszont további feltételt szab meg. Az elseif után következhet mégegy else is: • $a = 1; $b = 3; if ($a == $b) { print 'Az $a változó értéke egyenlô az $b-ével.'; } elseif ($a > $b) { print 'Az $a változó értéke nagyobb, mint az $b-é.'; } else { print 'Az $b változó értéke nagyobb, mint az $a-é.'; }
Elágazások • Van egy másik elágazásfajta is, ez az unless, mely nagyon hasonló az if-hez, különbség csak abban van, hogy míg az if használatánál a feltétel utáni utasításblokk akkor került végrehajtásra, ha a feltétel igaz volt, itt épp ellenkezőleg, akkor kerül végrehajtásra, ha a feltétel hamis: • $a = 10; $b = 2; unless ($a < $b) { print '$a nagyobb, mint $b'; } else { print '$b nagyobb, mint $a'; }
rand, int • Az első függvény a rand, mely egy random (véletlenszeru) számot fog visszaadni, 0 és az első paraméter értéke között (a paramétert az előző számban tárgyalt szubrutinok meghívásánál megismert módszer szerint adhatja meg). Ha nem adunk meg paramétert, akkor a szám 0 és 1 között lesz. Nézzünk egy példát! • $szam = rand(5); print "Véletlenszeru szám: $szam"; • A kimenetre ez kerül: • Véletlenszeru szám: 2.57788696289062 • Persze ez a szám minden futtatáskor más (nagyon kicsi annak az esélye, hogy ugyanazt az értéket írja ki). Mint látható, egy tört számot ad vissza a függvény (általában), ezért ajánlott az int függvény használata, mely egy számnak veszi az egész részét: • $szam = 6.454635435768634; print int($szam); #kiírja, hogy 6
Példa • Most pedig készítsünk el egy programot, amelynek egy fiktív háromszög oldalainak hosszát megadva megmondja, hogy a háromszög derékszögű-e. Ehhez a Pitagorasz-tételt fogjuk alkalmazni, azaz derékszögű háromszögben a2+b2=c2. • print "Add meg egy háromszög három oldalának a hosszát egységekben!\n"; #adatok felvétele (a három oldal: $a, $b, $c) print "Az elsô oldal: "; chomp($a = ); print "A második oldal: "; chomp($b = ); print "A harmadik oldal: "; chomp($c = ); #adatok vizsgálata (a^2 + b^2 = c^2 ?) if ( $a**2 + $b**2 == $c**2) { #ha igaz print "Ez egy derékszögu háromszög!"; } else { #ha hamis print "Ez sajnos nem derékszögu háromszög!"; }
Ciklusok • Tekintsük meg az első fajtáját a ciklusoknak, a while utasítást. Arra szolgál, hogy amíg a kifejezés logikai értéke igaz, addig mindig végrehajtja az utasításblokkot, ha a kifejezés hamissá válik, a program futása az utasításblokkot lezáró } után folytatódik. Tekintsen meg egy egyszerű példát! • $a = 3; $b = 10; while ($a < $b) { $a++; } • Két skalár került létrehozásra, $a és $b. Ezután egy while ciklus addig ismételgetett egy utasításblokkot, amíg $a értéke nem lett nagyobb $b-nél, az utasításblokkban pedig $a értéke került növelésre. Akkor hogyan is zajlott le a program lefutása? Mivel $a értéke 3, $b pedig 10, ezért az $a < $b feltétel igaznak bizonyult. Ekkor a program lefutatta az utasításblokkot, melyben $a értéke növelésre került eggyel, így az értéke már 4 volt. Azonban ez még mindig kisebb, mint az $b értéke, tehát megint lefutott az utasításblokk. És ez így ment mindaddig, amíg $a értéke el nem érte a 10-et, akkor ugyanis még egyszer lefutott az utasításblokk (tehát ha a program végén kiírattuk volna $a értékét, akkor 10-et írt volna ki), és itt lett vége.
until • A while „testvére” az until, mely ugyanazt csinálja, mint a while, annyi különbséggel, hogy az utasításblokkot addig ismételgeti, amíg a feltétel igazzá válik. Tekintsük meg az előző példát az until használatával! • $a = 3; $b = 10; until ($a >= $b) { $a++; } • Az eredmény ugyanaz lesz, mint az előző példánál. Azonban itt a relációjel megfordításán kívül egy = jel is bekerült, mivel ha az nem lenne, és szigorúan nagyobbnak kellene lenni a $a-nak a $b-nél, akkor a ciklus után az $a a 11 értéket kapná, mivel ha a két változó már egyenlő lenne egymással, még akkor sem lenne a kifejezés értéke igaz (true).
do .. while, do .. until • A while és az until párja a do.…while és a do…until. Ezek a szerkezetek valójában nem léteznek Perl-ben, azonban egy do függvény segítségével előállíthatók, akkor használjuk őket, ha azt szeretnénk, hogy az utasításblokk végrehajtásra kerüljön, mielőtt a kifejezés kiértékelése megtörténne. Tekintsünk meg egy példát! • $szam = 0; do { $szam++; print "$szam;"; } while ($szam < 10); • A kimenet az alábbi lesz: 1;2;3;4;5;6;7;8;9;10; • Az $szam skalár a 0 értéket kapta, majd az utasításblokkban az értéke növelésre, majd kiírásra került mindaddig, amíg az értéke kisebb volt, mint tíz (mivel a kiértékelés a végrehajtás után történik, még a 10-es is kiírásra kerül). A do…until-al a fenti példa az alábbi módon oldható meg: • $szam = 0; do { $szam++; print "$szam;"; } until ($szam >= 10); • A kimenet ugyan az lesz, mint a fenti példánál. A >= operátorra azért volt szükség, hogy a kiértékelés igazzá váljon, ha az $szam a 10-es értéket kapja, mert ellenkező esetben a 11-es is kiírásra kerülne.
do .. while, do .. until, for • Töltsünk fel egy tömböt számokkal, a do…while segítségével! • $szam = 0; do { $szam++; push(@szamok,$szam); } until ($szam >= 10); • A @szamok tartalma: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. • A következő ciklusszerkezet az egyik leggyakrabban használt, és egyben a legösszetettebb, a for ciklus. A szintaktikája valahogy így néz ki: • for (kezdeti érték; ellenőrzés; érték megváltoztatása) { utasításblokk } • A kezdeti értékben egy változónak egy alapértéket adunk meg, majd az ellenőrzésnél egy kifejezést készítünk, melyben ezt a változót vizsgáljuk, ez után pedig a változó értékét módosíthatjuk.
for • A ciklus futása ezek után úgy fog kinézni, hogy létrehozza a változót a kezdeti értékkel, majd azt megvizsgálja a kifejezésben megadottak szerint, és ha a kifejezés nem igaz, akkor lefut az utasításblokk, és elvégzi a változtatást a változón, majd újra ellenorzi, és ha így már igaz a kifejezés, akkor továbblép, és folytatja a futást a for ciklus után, ha még mindig nem igaz, akkor újból végrehajtja a változtatásokat, és így tovább. Tekintsünk meg egy egyszerű példát! • for ($x=0; $x<10; $x++) { print "$x\n"; } • Ez a ciklus kiírja az egész számokat 0-9-ig, egymás alá. Egy másik példa, mely ugyanazt csinálja, mint a fenti, csak csökkenő sorrendben írja ki a számokat: • for ($x=9; $x>=0; $x--) { print "$x\n"; } • A kimenetre egymás alá kerülnek a számok, 9-0-ig. Az $x kezdeti értékként a 9-et kapta, majd a vizsgálatnál az operátor “nagyobb, vagy egyenlő” volt, mivel ha csak “nagyobb” lett volna, akkor a 0 kimaradt volna a számsorból (ebben az esetben –1-et kellett volna írni a 0 helyére, így már 0-ig ment volna a számsor).
for • For ciklus segítségével kiírathatjuk egy tömb összes elemét: • @tomb = ("monitor","egér","nyomtató","billentyűzet"); for ($x=0; $x<@tomb; $x++) { print "$x. elem: $tomb[$x]\n"; } • A kimenetre az alábbiak kerülnek: 0. elem: monitor 1. elem: egér 2. elem: nyomtató 3. elem: billentyűzet
foreach • A for ciklus másik fajtája a foreach ciklus, mely egy értéklistán megy végig, például egy tömbön, és minden értéket egy változóba másol. Tekintsük meg egy, az előzőhöz hasonló példát a foreach ciklus használatával! • @tomb = ("monitor","egér","nyomtató","billentyűzet"); print "A tömb elemei:"; foreach $elem (@tomb) { print " $elem;"; } • A kimenetre pedig az alábbi sor kerül: • A tömb elemei: monitor; egér; nyomtató; billentyűzet;
foreach • Az alábbi példa egy Hash elemeit listázza ki: %sokminden = ("gyümölcs" => "alma", "virág" => "rózsa", "madár" => "gólya"); foreach $kulcs (keys %sokminden) { print "$kulcs: $sokminden{$kulcs}\n"; } És a kimenet: virág: rózsa gyümölcs: alma madár: gólya
redo • A redo operátor, mellyel a kifejezéstől függetlenül még egyszer végrehajtódik az utasításblokk. Tekintsünk meg egy példát! • @szamok = (1..10); foreach $szam (@szamok) { $szam++; if ($szam < 20) { redo; } print "$szam "; } • Itt egy tömböt hoztunk létre, melynek elemei 1, 2, 3, … 9, 10 – a tartományoperátort használtuk, melyről már volt szó. Aztán egy foreach ciklussal mentünk végig az értékeken, és mindet növeltük eggyel. Aztán megvizsgáltuk, és ha értéke kisebb volt, mint 20, akkor a redo segítségével itt megszakítottuk az utasításblokkot, és elölről kezdtük, tehát, megint növeltük az értéket. Ha az érték már 20 volt, akkor az if elágazásban a kifejezés már nem volt igaz ($x < 20), ezért az érték kiírásra került. Ez a folyamat zajlódott le az összes tömbelemnél, így tíz db 20-as került a kimenetre.
redo • A redo segítségével ciklusokat is készíthetünk egyszerű utasításblokkokból: • $szam = 1; { if ($szam < 10) { $szam++; redo; } } print "\$szam értéke: $szam"; • Egy utasításblokkot készítettünk, melyben megvizsgáltuk $szam értékét, és ha kisebb volt, mint 10, akkor növeltük az értékét, és újra végrehajtattuk az utasításblokkot. A kimenetre ez került: $szam értéke: 10
next • Ez az operátor arra való, hogy az utasításblokk végrehajtását megszakítsuk, és azonnal a következő ciklusra ugorjunk. Nézzünk meg egy ciklusszerkezetet, mely felsorolja egy tömb elemeit, kivéve a második elemet: • @tomb = ("processzor","alaplap","memória","háttértár","meghajtó"); for ($x=0; $x<@tomb; $x++) { if ($x eq 1) { next; } print "$tomb[$x]\n"; } • A kimenet: processzor memória háttértár meghajtó • Mint látható, a tömb elemei felsorolásra kerültek, kivéve a második elemet, mivel ha az aktuális tömbelem számozása 1 volt, akkor a next utasítás hajtódott végre, ergo kimaradt a tömbelemet kiíró sor.
last • A last operátor hasonló a next-hez, mivel itt is ugyanúgy megszakítja az utasításblokk végrehajtását, csak itt nem a következő ciklusra ugrasztja, hanem teljesen kilépteti a ciklusszerkezetből a program futását. Tekintsük meg a fenti példát a last használatával! • @tomb = ("processzor","alaplap","memória","háttértár","meghajtó"); for ($x=0; $x<@tomb; $x++) { if ($x eq 1) { last; } print "$tomb[$x]\n"; } • És a kimenet pedig: • processzor • A program futása hasonlóképpen zajlott az előzőhöz, viszont itt a második elem átugrása után végleg elhagyta a ciklusszerkezetet.
Helyettesítés • Helyettesítések segítségével egy mintát kereshetünk egy sztringben, találat esetén pedig a mintát egy másikra cserélhetjük. Egy egyszerű példa: • $betuk = "abcd"; $betuk =~ s/a/b/; print $betuk; • A program a skalárban az “a” betűt b-re cserélte, a helyettesítés szintaktikája tehát: • s/helyettesítendő minta/mire cserélje/ • Ezek után nem meglepő, hogy a kimenetre “bbcd” kerül. Mivel itt is mintaillesztésről van szó, használhatók a múlt számban ismertetett mintaillesztésnél használatos operátorok is, az alábbi program például a sztringben lévő számot és az előtte szereplő karaktert felcseréli: • $sztring = "abcde9fgh"; $sztring =~ s/(.)([0-9])/$2$1/; print $sztring; A program kiírja, hogy abcd9efgh. A mintánál egy tetszőleges karaktert adtam meg, melyet egy szám követ, persze mind a kettőt zárójelek között, így a talált karakterek eltárolódtak a $1 és a $2 változóba, így a helyettesítő sztring helyére csak ezt a két változót adtam meg felcserélve ($1$2).
Helyettesítés • $a = "haaaaaah"; $a =~ s/a{3,}/i/; print $a; $b = "haaaaaah"; $b =~ s/a{3,4}/i/; print $b; • $a és $b értékében hatszor szerepel egymás után az a betű. Először egy mintaillesztést hajtunk végre, amelyben ha háromszor, vagy többször szerepel az “a”, akkor lecseréljük azokat egy “i”-re. Ekkor a program kiírta, hogy hih, mivel nem adtunk meg maximális értéket a keresendő a betűk számának a megadásakor. Másodjára, $b eseténél viszont már megadtam maximális értéknek a 4-et, így a kimenetre az került, hogy “hiaah”, mert az illesztés maximum 4 db a betűre vonatkozik. • A következő példa a szavak közti szóközök számát egyre csökkenti, amennyiben több is megtalálható: • $a = "több szóköz a szavak között"; $a =~ s/ +/ /g; print $a; • A sokszorozót (ez esetben a + jelet, de lehetett volna {1,} vagy {2,} is) ez esetben egy szóköz után tettük, így a program az egyszer, vagy egynél többször szereplő szóközöket kereste. A kimenet: • több szóköz a szavak között
Helyettesítés • Az alábbi opciók használhatók a helyettesítő operátornál: • g – többször is illeszt i – nem különbözteti meg a kis és a nagybetűket • Egy példa: • $a = "haaaaaa"; $a =~ s/a/i/; print $a; $b = "haaaaaa"; $b =~ s/a/i/g; print $b; • A kimenetre először az kerül, hogy hiaaaaa, másodjára az, hogy hiiiiii. Mint látható, alapértelmezésben a Perl csak egyszer végzi el az illesztést, azonban a g opció használatával már az összes “a” betűt lecserélte. Példa az i használatára: • $a = "kisbetuNAGYBETU"; $a =~ s/un/u_N/; print $a; $b = "kisbetuNAGYBETU"; $b =~ s/un/u_N/i; print $b; • Ebben az esetben $a és $b olyan értéket kapott, amelyben szerepel kis- és NAGY betu is. Az elo esetben csak a szokásos módon hajtottuk végre a cserét, ezért a minta nem volt illeszthető, mivel a Perl különbséget tesz a kis- és a nagy betűk között [Az “un” nem egyenértékű “uN” -el], ezért a kimenetre “kisbetuNAGYBETU” került. A második esetben, az i funkció használatával a Perl már egyenértékűnek vette az “un”-t az “uN” –el, így végrehajtotta az illesztést, a kimenetre itt már “kisbetu_NAGYBETU” került.