Perl 4


Perl - Practical Extraction and Report Language

( pro ty kdo neumi englictin, volne prelozeno "Prakticky jazyk pro export a report" :)

Perl je skriptovy jazyk pro praci se soubory a ruznymi datovymi formaty. Je take velmi uzitecny na mnoho systemovych vecicek :) ( Kdo zna Satana ten jiste vi o cem je rec :).

Perl stvoril Mr. Larry Wall. Autor tvrdi, ze vybral to nejlepsi z C, awku, sedu a BornShelu a tim vznikl PERL. Kdyz zde budu hovorit o PERLU myslim tim PERL 4.

Provadeni perlovskeho skriptu neni klasicky interpretovene, jako u shellu, ale perl nejdrive prelozi skript do pseudokodu a skontroluje syntaxi a potom tento pseudokod spusti.


Promenne

Promenne se nemuseji nikde deklarovat a jsou vytvoreny pri prvnim pouziti. Kazdy typ ma vlasni domenu jmen ( muze existovat pole s nazvem 'fero' a skalar s timtez nazvem :).

Skalary

Skalary mohou byt bud cislo nebo retezec.

V perlovskem skriptu maji skalary nasledujici syntaxi:
 $jmeno_skalaru

   napr:
 $hmotnost, $delka ...
Cislo muze byt zadano v nasledujicich tvarech:
 $hmotnost=12; # cislo v desitkove soustve
 $pi=3.1415;   # desetinne cislo
 $ro=.12e-4;   # desetine cislo vyjadrene pomoci mantisi a exponentu
 $hexa=0xff;   # hexadecimalni cislo
 $prava=0777;  # oktanove cislo ( nema nic spolecneho z benzinem :)
 $prehled=123_456_789 # tohle by mel byt prehledny zapis pro oddeleni tisicu
Retezec muze vypadat nasledovne:
 $hurvinek='vyhral $nic'; # neinterpretovany retezec

    vytiskne se: vyhral $nic

 $neco = 100
 $manicka="vyhrala $neco"; # interpretovany retezec

	vytiskne se: vyhrala 100

Pole

Perlovske pole mohou byt pouze jednorozmerna, ale zato mohou mit prvky pole ruzny typ ( tedy mohou byt skalary nebo hase ( pole se rozexpanduje do posloupnosti promennych ) :)
V perlovskem skriptu maji pole nasledujici syntaxi:
 @jmeno_pole # cele pole
 $jmeno_pole[index] # jedna polozka pole

  napr:
 @parky,@mesta
 $parky[2],$parky[123]
Jak je videt z predchoziho, Perl neumoznuje zadat velikost pole. Velikost pole je v podstate gumova, tedy mohu indexovat (indexuje se od nuly) do nekonecna (pole se automaticky reexpanduje :).
Zadani poly v perlu muze vypadat nasledovne:
 @parky = ( 1, 2, 3 ); # pole o trech prvcich
 $parky[10] = 10; # pole se automaticky reexpanduje takze ma 11 prvku
             # zbytek nedefinovanych prvku, ktere patri do pole jsou nahodna
 
 @humus=("Nazdar svete", 1, %juk); # pole s ruznymi typy prvku

 $#jmeno_pole # promenna v ktere je ulozena aktualni velikost pole

 print $#parky;
 vytiskne: 11

Hase neboli hasovaci tabulky

Hase neboli asociativni tabulky jsou obdobou poli, ale k jednotlivym polozkam se nedostanu pres ciselny index, ale pres index, ktery je retezec. O velikosti hasu plati to same co o polich.
Hash vypada nasledovne:
 %Jmeno_hase # cela asociativni tabulka
 $Jmeno_hase{ retezec } # jedna polozka

  napr:

 %opcode = ( 'mov', 0, 'and', 1, 'or', 2 ); # zadani celeho hase
 $opcode{ 'xor' } = 3; # zadani pouze jedne polozky

 No a kdyz se bude pokracovat dal tak z toho budu mit jednoduchy kompiler :) 

Syntaxe

Cely zdrojovy kod tvori tzv. BLOKY.

BLOK = { posloupnost prikazu oddelena stredniky }


Prikazy mohou byt prikazy pro podminene rizeni programu ( skratka EXP znaci logicky vyraz):

if (EXP) BLOK
Jestli-ze plati EXP pokracuj v BLOK

if (EXP) BLOK else BLOK1
Jestli-ze plati EXP pokracuj v BLOK jinak pokracuj v BLOK1

if (EXP) BLOK elsif (EXP1) BLOK1 elsif (EXP2) BLOK2 ... else BLOKE
Jestli-ze plati EXP pokracuj v BLOK jinak jestli-ze plati EXP1 pokracuj v BLOK1 ... jinak pokracuj BLOKE

while (EXP) BLOK
Dokud plati EXP provadej BLOK

while (EXP) BLOK continue BLOK1
Dokud plati EXP provadej BLOK a zanim provadej BLOK1

for(EXP1;EXP2;EXP3) BLOK
Na zcatku proved EXP1 a dokud plati EXP2 provadej BLOK a potom vzdy proved EXP3 ( EXP1 a EXP2 byvaji vetsinou prirazovaci prikazy :)

foreach VARIABLE (LIST) BLOK
Pro kazdou polozku z listu promenych prirad tuto promenou VARIABLE a provadej BLOK ( LIST = (promena1,promena2, ... ) :)

LABEL: ... goto LABEL;
Skoc na misto programu oznacene LABEL;

Nebo to mohou byt prikazi, ktere pracuji z ruznymi operatory.
 Par prikladu na rozmlzenou:

 SEM:			 # definuje se navesti SEM
  $citac = 10;	 # do promenne citac se priradi 10
  if ( $citac > 0 ) { $citac--; }  # pokud je citac > 0 sniz citac o jednu
  else { goto PRIC; }			   # jinak skoc na PRIC
  goto SEM;		 # skoc na SEM
 PRIC: 			 # definuje se navesti PRIC 

 for( $citac=10; $citac > 0; $citac--) {} # to same, ale kratsi :)

 foreach $citac ( 10 .. 1 ) {} # to same, ale jeste kratsi

        !!!!!!!!!!!!!!!!!!!! POZOR CECKARI !!!!!!!!!!!!!!!!!!!!!!!!

  Nelze udelat:
   if ( $citac > 0 ) $citac--;  # vyhodi chybu :)

Operatory

Operatory v perlu jsou velmi podobne operatorum v jazyce C. Uvedu je zde v poradi podle priority( sestupne :)

( $a, %s, @d ) operator listu - seznam promennych

 Operator listu udela z promennych seznam promennych s kterym se da dale 
 pracovat jako s polem.


  @pole=($prvniprvek,$druhyprvek); % 0 a 1 prvku @pole hodnotu $prvni a $druhy prvek
  ($a,$b,$c)=($d,$e,$f); % to same jako $a=$d;$b=$e;$c=$f
++, -- increment a decrement o jedna
 $a++; # to same jako $a = $a + 1;
 $b--; # to same jako $b = $b - 1;
** operator umocneni
 $a = 2**n; # $a se priradi dve na n-tou
!, ~, unarni (+,-) logicke not a bitova negace, unarni plus a minus
 if ( !podminka ) { $c--; } # probehne pokud neni splnena podminka
=~,!~ operator pro praci z paterny textu
 $a=~ Regularni vyraz # o reg. vyrazech bude rec dale
                      # pokud byl reg. vyraz splnen vrati hodnotu 1 jinak 0

 $a!~ je presny opak =~

 if ( $a=~/ahoj/ ) { print "nazdar"; } 
            # kdyz je v retzci $a 'ahoj' vytiskne nazdar
*, /, %, x operatory nasobeni,deleni,modulo a opakuj
 $a = 2*3; # vynasobi 2 a 3 a priradi do $a

 print "-" x 80; # 80 krat vitiskne '-'
+,- operatory scitani a odcitani
 kdo neumi scitat a odcitat at si hodi masly :)
<<,>> operator bitoveho bosunuti doleva a doprava
 $a = 2 << 2; # posune doleva bity operandu o zadany pocet a tim vznikle
              # nespecifikovane bity po posunuti se vynuluji
			  # v $a bude 8
 $a = 8 >> 2; # jako << ale opacne
              # v $a bude 2
&nazdar($ahoj) operator funkce
 &jajsemfunkce( $ajaparametr ); # zavola fci. jajsemfunkce s parametrem aja..
<,>,<=,>=,lt,gt,le,ge operatory porovnani pro cisla a retezce
 <   operator mensi 1<2 ( je pravda )
 >   operator vetsi 2>1   -"-
 <=    ""	  mensi nebo rovno 3<=3 ""
 >=  vetsi nebo rovno 4>=4 ""
 lt  mensi pro retezce "a" lt "ab" ""
 gt  vetsi pro retezce "ab" gt "a"  ""
 le  mensi nebo rocno pro retezce "aa" le "aa" ""
 ge  vetsi nebo rovno pro retezce "aa" ge "aa" ""
==,!=,eq,ne,cmp operatory rovnosti pro cisla a retezce
  if ( $a == $b ) { print "a se rovna b"; } # jeli $a rovno $b pak ..
  if ( $a != $b ) { print "a se nerovna b"; } # nenili $a rovno $b pak ..
  if ( $a eq $b ) { print "ret a je shodny s ret b"; } # jeli $a rovno $b pak ..
  if ( $a ne $b ) { print "ret a je shodny s ret b"; } # nenili $a rovno $b pak ..

  $a cmp $b vrati -1 jeli $a mensi
                   0 jsouli oba shodne
				   1 jeli $a vetsi
  porovnani se provadi s ret.
& bitove and
 kdo nezna bitove operace at se jde vycpat :)
|,^, bitove or a xor
 to samy :)
&& logicke and
 if ( podminka1 && podminka2 ) { ... } # pokud plati obe podminky pak se provede...
|| logicke or
 if ( p1 || p2 ) { .. }	# pokud plati p1 nebo p2 pak ..
.. operator hranice
  foreach $a ( 1..10 ) { print "$a "; } # vitiskne 1 2 3 4 5 6 7 8 9 10
?: operator podmineneho prirazeni ( stejne jako v C )
 $a = ($b>0)?(-1):(1);

  shodne s :
 if ( $b>0 )
  { $a = -1; }
 else
  { $a = 1; }
=,+=,-=,*=,**=,/= atd. operatory prirazeni , prirazeni a pricteni ...
 $a=$b; %priradi hodnotu $b do $a
 $a+=2; je to same jako $a = $a + 2;
 .
 .
 .
I/O operatory
 '<'handle'>' - operator pro praci se souborem, ktery ma pridelen handle

 open(handle,"muj.sou"); # pridely handle soubru muj.sou
 while ( $a='<'handle'>' )
 {
  print $a;  # dokud je co nacitat tak to tiskni :)
 }

 while ( '<'hanlde'>' ) { .. } # standartne nacita do promenne $_

 STDIN a STDOUT jsou vyhrazene hanly pro praci s vstupnim a vystupnim 
 zarizenim
 <*.c> - ctenim tohoto handlu postupne dostanete vsechny soubory v adr. s 
         priponou .c

Regularni vyrazy

Regularni vyrazy slouzy k jednoduchemu a efektivnimu zachazeni s vyrazy ( pokud to tedy clovek pochopi :). Je to jedna s nejpouzivanejsich nastroju, ktery perl poskytuje.
Pro nazornost mate nejaky textovy soubor kde na prvnim miste je nazev clobrdy a dale za nim oddelene mezeramy jsou pro vas jiste dulezite informace, ale ted prave poterbujete udelat vytazek pouze jmen z tohoto souboru a co ted : a) udelat to rucne b) udelat to rucne c) udelat to rucne :) nebo poridim si prirucku perlu ci se juknu na tuto stranku a udelam si jednoduchy skryptik, ktery to vse udela za vas a bez na maceni :) ( ooo to se budeme mit :)

Nu zapocnemez mlzit:
Nejdrive par definic:
\   .. oznacije nasledujici metacharakter ( terba zrovna \ )
^   .. oznacuje zacatek retezce
.   .. oznacuje jakykoliv znak krome nove radky
$   .. oznacuje konec retezce
|   .. nebo
()  .. gruping ( vse co je v zavorce se bere jako jeden retezec )
[]  .. vse co je v zavorce se bere co by mohlo byt napr [a,b] muze byt a nebo b

*     .. oznacuje vyskyt 0 az nekonecnekrat
+     .. oznacuje vyskyt 1 az  ""
?     ..  ""        ""   1 nebo 0
{n}   ..  ""        ""   prave n-krat
{n,}  ..  ""        ""   nejmene n-krat
{n,m} ..  ""        ""   nejmene n-krat, nejvice m-krat

ted par preddefinovanych maker
\w    .. oznaci znak ( alfanumerycky znak + "_" )
\W    .. opak \w
\s    .. byloznakove znaky ( mezera tabelator .. )
\S    .. opak \s
\d    .. cislo
\D    .. opak \d

 no kdyz se clovek zamysli, tak muze jednoduse rict, ze
 \w je to same jako [a-z,A-Z,0-9,_] :) jak jednoduche, ze ?

A ted nejaky priklad:

 $_ = "ahoj ja jsem JA"; # tady s tim retezcem se to bude vsechno dit
 /^\w+\s+(\w+)/; # zacatek str. nejaky pismena pak mezery a oznac dalsi
                 # pismena za tim a to oznaceny dej do prvniho nepouziteho
				 # registru oznacenych retezcu $1 .. $9
 print $1; # no ted se jukni co jsi vybral :)

  Tak tohle vytiskne ja


Subrutiny

Subrutiny neboli casti programu, ktere jsou samostatnou jednotkou, ktere provadi urcity specificky ukol jsou samozrejmne i v perlu. Definice subrutiny je nasledujici:
 sub jmeno_subrutiny BLOK
Parametry jsou predavany v poly @_. Volani se provadi vlozenim jmena do programu pred, kterym je & a zanim seznam parametru.
 sub hodneslozita
 {
  foreach ( @_ )
  {
   print "$_, ";
  }
 }
Co asi dela tato velmi slozita rutina ? 

 ...
 &hodneslozita($a,$b,"nazdar");
 ...

 Cele to vytiskne hodnotu $a a $b a potom nazdar.
No a jak udelat subrutinu, ktera neco vraci( neco jako Ceckovka fce. )? Nakonec subrutiny pred zavorky uzavirajici blok staci napsat promennou, ktere hodnota se ma vratit:
 sub varcimto
 {
  $i = $_[0];
  $i;
 }

 ..
 print &vracimto("ahoj");
 ..

 Vytiskne ahoj :)
Localni promene se vytvareji pomoci fce. local( promenne ) = hodnota.
sub .. {
 local( $a ) = $_[1];
 ..
}

MODULY

Pokud clovek pise velky projekt nema smysl ho cely napsat do jednoho souboru. Jednak to bude neprehledne a jednak kdyz se mu s nim neco stane tak ma vsechno v haji :). Takovyto velky program se da rozdelit na nekolik mensich logicky uzavrenych celku. K tomu prave slouzi moduly. Moduly mohou byt take ruzne knihovny. Pokud chci vyuzivat fce. nektereho modulu musim to programu zdelit nazledovne:
 require "potrebujite";
A pak mohu pozivat fce. a promenne definovane v modulu poterbujite :). Struktura modulu neni pevne dana a proto si ho kazdy muze udelat jaky chce. Pouze musi byt na posledni radce "1;".
 priklad:

 potreb:
-----------------------------
 package potreb; # nazev modulu ( neni poviny )
 sub potrebna
 {
  print "$_[0]";
 }
 1;
-----------------------------

 progr:
-----------------------------
 require "potreb";

 ..
 potrebna("nazdar");
 ..
-----------------------------


Formatovani

Pokud chceme mit vystup pekne upraveny ma perl jeden nastroj, ktery nam s tim pomuze. Je pro to pouzit prikaz 'format':
 format handle =  # musi byt handler nejakeho souboru
 ..               # neco
 .				  # konec

 $a = "dol";
 $b = "vyst";
 $c = "dop";
 # nadefinuj format 
 format STDOUT =
   zarovnej:
   doleva     vystredi     doprava
 @<<<<<<<<< @||||||||||| @>>>>>>>>>>
 $a,        $b,          $c
 .
 write STDOUT; # a ted ho hezky vytiskni

 vytiskne:
   zarovnej:
   doleva     vystredi	doprava
   dol          vyst		dop