Fujtajbl vespolek..
V posledních dvou týdnech jsem byl nucen svým zaměstnavatelem oprášit své znalosti perlu. Tento článek je myšlen pouze jako malý úvod a závdavek pro toho, kdo neví o perlu zhola nic a má dostatečně hladový mozek a energie na to, aby se začal něco sám učit.
Na úvod je třeba zdůraznit, že pro alespoň lehce angličtinou dotčeného jedince, je o perlu
skutečně mnoho kvalitní dokumentace v samotném systému v rámci manuálových stránek. Víc než 'man perl && man perltoc && man perlfaq' na začátek není třeba.
Co to je Perl?Perl je univerzálně použitelný programovací jazyk původně vyvinutý jako nástroj pro manipulaci s textem a nyní rozšířený do vysokoúrovňového skriptovacího jazyka, který je schopen pokrýt většinu úkolů, pro které jsou nízko (assembler, ..) a středně (C/C++) úrovňové jazyky neohrabané.
Typické použití Perlu je jako mocná, rychlá a příjemná náhrada veškerého systémového skriptování a manipulace s textem a soubory za použití RE (regulární výrazy) namísto dnes již nepříliš konfortního jazyku awk a případně kombinace klasických nástrojů jako bash+awk+sed.
Perl podporuje OO (object-oriented) programování a říkám rovnou a dopředu :: začnete-li s Perlem, začněte rovnou OO, protože použitím modulů si ušetříte
skutečně mnoho řádků vašeho programu a jak jedna stará prava říká: "no problem should be solved twice", moduly v perlu (pro ty, kdo stále ještě nerozumí o čem je řeč, tak modul je vložený objekt podobně jako v C '#include <math.h>') dnes pokrývají nezměrnou množinu všech běžných i exotických operací.
(Pro toho, kdo stále ještě nerozumí:: Perl samořejmě umí provést příkazy systému a píšeme-li systémový skript právě v něm // a začínáme -li s Perlem // máme bez použití OO velice často nutkání provádět určité operace přímo pomocí systémového interpretu namísto použití možností samotného Perlu, takže takový systémový skript začínajícího programátora v Perlu je pak často mix bashe (`ls -a`) a řídících struktur perlu).
Více o OO viz. 'man perlmod && man perlmodlib'.
Na závěr obecných informacích o Perlu je třeba zdůraznit, že česká dokumentace a manuály k perlu je bohužel dnes již lehce překonaná a evergreenová dílka, která lze z vod českýho internetu vylovit, jsou bohužel často 10let stará a tudíž nemoderní a zbytečně zjednodušující.
Jak začít?Třeba tak, že si řekneme, že každý program v Perlu by měl začínat '#!/usr/bin/perl -w'. Ono '-w' tam není nutné, ale znamená, že budeme dostávat upozornění na nepřiřazené proměnné a jiné věci, které nejsou nejsou přímo chybou. Náš styl se tím pak vytříbí, protože jen bez upozornění, je náš program v tomto směru napsaný čistě.
Komentář je od znaku '#' do konce řádku, pokud to není v RE.
Začnem složitější verzí oblíbeného programu 'Hallo World!', který se v tomto případě bude jmenovat pozdrav.pl a vytiskne 'Hallo World!' pokud ho spustime bez parametru a jinak 'Hallo <parametry>!' (takze pokud spustime aka 'pozdrav.pl Pepa Novak' dostaneme 'Hallo Pepa Novak!'
(dále od tohoto řádku píši jako by to byl samotný program, takže komentáře začínají od '#' do konce řádku)
# od teď si pro lepší pochopení doporučuju příklady
pastnout do editoru, který má nějakou 'syntax-highlight' ..
# samozřejmě je jasné, že na prvním řádku (což dále už nezdůrazňuji) musí stát::
#!/usr/bin/perl -w
print "Hallo World\n" unless @ARGV;
print "Hallo @ARGV!\n" if @ARGV;
exit 0;
# o '@ARGV' zatím potřebujeme vědět pouze to, že to jest speciální (vyhrazenná) proměnná obsahující všechny parametry příkazové
# řádky, se kterými jsme program spustili. V tomto nejjednoduším případě testu dostaneme 'true', pokud není @ARGV prázdná.
# Tento příklad byl zapsán typickým způsobem pro perl, což je semantika anglického jazyka spojená se C-like syntaxi. Někomu bude
# možná připadat tento zápis ze začátku přehlednější, jinak je to absolutne to samé ::
if(@ARGV) {
print "Hallo @ARGV!\n";
} else {
print "Hallo World!\n";
};
exit 0;
# všiměte si, že náš program je ukončen pomocí příkazu 'exit 0', což sice není nutné, ale každý slušný 'program pod kontrolou'
# by tak měl být ukončen.
# V rámci geniálního použití syntaxe anglického jazyka v kombinaci s programováním může náš příklad vypadat v rámci možností
# Perlu i následovně ::
print "Hallo World!\n" and exit if not @ARGV or
print "Hallo @ARGV!\n" and exit;
# V posledním příkladu si všiměte, kde nám končí příkaz (kde je ';').
# 'if not VYRAZ' je to samé co 'unless VYRAZ', 'if ! VYRAZ' a nebo 'if(!VYRAZ)'.
# 'and', 'not' a 'or' jsou v tomto případě operátory. Jak vidíte, závorka kolem podmínky není povinná, ale
# nelze se na to spolehnout vždy a platí tedy zláté pravidlo jazyka C :
Máš-li pochyby, závorkuj!# Tento způsob byl pouze demonstrace kombinace angličtiny s programováním v perlu a takovýto zápis ve skutečnosti asi mnoho
# programátorů nepoužije.
# V následujícím příkladu si rozšíříme náš program tak, že víc argumentů příkazové řádky bude považovat za více jmen a
# přidáme podmínku, díky které nepozdraví slušně Billa Gatese, pokud se vyskytne mezi jmény.
# Samozřejmě platí, že chceme-li předat 'Bill Gates', musíme to buď dát do uvozovek a nebo vyescapovat mezeru aka 'Bill\ Gates'.
# to je samozřejmě vlastnost Bashe a s Perlem to nemá co dělat.
# Jako první způsob zápisu uvedu konzervativní C-like syntaxi ::
if(@ARGV) {
foreach(@ARGV) {
if($_ =~ m/bill\ gates/i) {
print "there are no greetings for bill!\n";
} else {
print "Hallo $_!\n";
};
};
} else {
print "Hallo World!\n";
};
exit 0;
# trocha si náš příklad "podáme" ::
# Ale předtím, než si řekneme co to je cyklus 'foreach', si ještě uděláme malou odbočku k proměnným ::
# proměnné v perlu mohou být buď 'string' (skalarní proměnná), což je nejjednodušší typ proměné a má prefix '$',
# a nebo 'array' jako pole, což je parta stringů nastrkaná do proměnné s prefixem '@'.
@VSTUP = @ARGV; # duplikujeme pole @ARGV jako pole @VSTUP
$VSTUP = "@ARGV"; # přiřadíme obsah pole @ARGV jako řetězec do skalarni proměnné $VSTUP
$VSTUP2 = @ARGV; # přiřadíme počet prvků pole @ARGV do proměnné $VSTUP2
print "$VSTUP[0]\n"; # tiskneme prvni prvek (indexovany jako '0') pole @VSTUP
print "$VSTUP\n"; # tiskneme skalarní proměnnou $VSTUP. !! nemá nic společného s polem @VSTUP
print "$VSTUP2\n";
exit 0;
# Z příkladu je patrné, že jednotlivé prvky pole jsou přístupné pomocí
indexu [0..x], kde 'x' je poslední prvek
# pole a můžeme ho získat také jako ::
print "$ARGV[$#ARGV]\n"; # tedy '$#ARGV' je ve skalárním kontextu (číslo) index posledního prvku @ARGV.
# z příkladů výše je taktéž patrné, že Perl je inteligentní a rozlišuje jako různé proměnné $VAR a @VAR ..
# pozor! prvek pole nás zajímá ve skalárním kontextu, takže se na něj ptáme jako $VAR
# jediný rozdíl by byl, kdyby nás jako pole zajímal pouze určitý rozsah indexu pole, potom bychom jako
# prefix mohli použít '@' ::
@VSTUP = @ARGV[0..1]; # vytvoříme nové pole @VSTUP, obsahující první dva prvky pole @ARGV
$VSTUP = "@ARGV[0..1]"; # vytvoříme skalární proměnnou $VSTUP obsahující jako řetězec
# první dva prvky pole @ARGV oddělené mezerou.. ('..' znamená rozsah.)
# Zpět ale k našemu zdravícímu programu::
# Cyklus 'foreach(@ARGV)' tedy proběhne tolikrát, kolik má pole @ARGV prvků a v každém průběhu bude manipulovat
# právě s jedním prvkem. O '$_' zatím potřebujeme vědět pouze to, že je to 'implicitní proměnná' a v kombinaci
# s 'foreach' obsahuje ve skalárním kontextu (jak jinak že, když má prefix '$') v každém průběhu aktuální prvek.
# další zajímavost je zde podmínka 'if($_ =~ m/bill\ gates/i)', kde operátor '=~' slouží k porovnání s RE, což
# je výraz uzavřený mezi '/' aka '/REGEXP/' a je zde syntaxe jako v sedu, tzn.::
$XX =~ s/xx/yy/; # nahradí ve skalární proměnné 'xx' za 'yy'
if($_ =~ m/bill\ gates/i) .. # splní se, pokud '$_' obsahuje ('m' jako match // odpovídat) "bill gates"..
# 'i' znamené case-insensitive // kdyby nás chtěl Bill převézt aka "bILL gAteS"
# jedna vychytávka na konec:
foreach(@ARGV) {
$_ =~ s/billy?\ gates/looser/i;
print "Hallo $_!\n";
};
# tyto 3 řádky normálně zdraví jako náš program výše, ale pokud se mezi jmény vyskytne 'bill gates',
# a nebo 'billy gates' (obyč RE: '?' značí nepovinný znak, kdyby byl bill skutečně záludný a pokusil se
# zamaskovat třeba jako 'billy gATes'), program ho nahradí slovem 'looser', takže pokusí-li se Billy
# pozdravit naším programem, dopadne následujícím způsobem::
# $ pozdrav.pl The\ Big\ Billy\ Gates
# Hallo The Big looser!
# $
# Jakékoliv jiné jméno se přirozeně dočká slušné odpovědi::
# $ pozdrav.pl "The Big Pepa Novák" Jarda\ Procházka The\ Master\ Mark\ Shuttelworth 'Jan Tleskač'
# Hallo The Big Pepa Novák!
# Hallo Jarda Procházka!
# Hallo The Master Mark Shuttelworth!
# Hallo Jan Tleskač!
# $
# A na závěr se ještě jednou podívejte na náš program výše, protože ho teď napíšu v naprosto stejné funkcionalitě,
# ale místo použité C-like syntaxe použiju typickou perlovskou syntaxi..
#
# Pevně doufám, že Vás tento malý úvod do Perlu alespoň trošičku zaujmul a snad i inspiroval k jeho podrobnějšímu
# ohledání, protože Perl je skutečně vyjímečný jazyk ..
print "Hallo World!\n" and exit 0 unless @ARGV;
foreach(@ARGV) {
print "there are no greetings for bill!\n" and next if($_ =~ m/bill\ gates/i);
print "Hallo $_!\n";
};
exit 0;
# a úplně na závěr si představte, jakej by tohle byl vopruz napsat v bashi..
;enjoy by ntz
;ps. A aby jste neřekli ještě nakonec že jsem Vás ošidil, tak zde jest verze tohoto programu v Bashi:
if [ -z "$1" ]; then
echo "Hallo World!"
exit 0
fi
for x in "$@"; do
if [ -z "$(echo "$x" | tr A-Z a-z | sed '/bill\ gates/d')" ]; then
echo "there are no greetings for bill.."; else
echo "Hallo $x!"
fi
done
exit 0
;pps. Bohužel mám v systému šeredný bug, který způsobuje děsivou pomalost vyhledávacího algoritmu v grepu při
; utf8 locale, takže proto zde řeším podmínku přes tr+sed a ne přes grep. Nicméně za poslední měsíc jsem
; si zvykl skutečně přirozeně, že "grepovat" jde sedem snad ještě důkladněji