10. Perl: základy
1. Úvod
Perl je skriptovací jazyk určený především pro zpracování textu. Mezi programátory je velmi oblíbený a rozšířený, má však špatnou pověst, protože je multisyntaktický a pro neodborníka velmi špatně čitelný. Přesto je velmi užitečný a při využití jen malé podmnožiny jeho vlastností je snadné v něm začít programovat.
Perl je ale také zákeřný programovací jazyk, v němž je podmínka „if (false)“ splněna, funkce length() aplikovaná na osmnáctiprvkové pole vrací hodnotu 2, připojovaný zdrojový soubor musí končit příkazem „1;“, proměnné se nejčastěji deklarují klíčovým slovem „my“ a příkaz náhrady „s/.$/@/“ provedený nad řetězcem "X\n\n\n" nikdy neskončí výsledkem "X\n\n@" jako v GNU Sedu, ale jedním z výsledků "X\n\n\n" (bez modifikátoru), "X\n@\n" (s modifikátorem „s“) nebo „X\n@@“ (s modifikátory „gs“); ke stejnému chování jako v Sedu ho však nedonutíte.
Kapitoly vanilkové příchuti Linuxu: Knihy kouzel zaměřené na Perl se omezují na bezpečnou podmnožinu jeho funkcionality, čímž vám umožní začít z jeho moci těžit velmi rychle a s minimem nutných znalostí a vyhýbat se přitom většině zákeřných pastí. (Pronikat do „hlubin Perlu“ můžete později. Nejdřív naprogramujte, co potřebujete.)
Tato kapitola nepokrývá moduly, objektově orientované programování a velkou část užitečných knihovních funkcí (např. práci s databázemi).
Poznámka: Všechna zaklínadla v této kapitole předpokládají, že máte nainstalovaný balíček DEB Linuxu: Knihy kouzel a skripty budete spouštět výhradně příkazem „lkk perl“. Informace, jak takové skripty zprovoznit bez něj, najdete v repozitáři Linuxu: Knihy kouzel na GitHubu.
2. Definice
- Skalár je dynamicky typovaná hodnota, která může být řetězec, číslo, ukazatel na nějaký objekt nebo zvláštní nehodnota undef. Výchozí hodnotou skalárů je undef. Jednotlivé skaláry se symbolizují znakem „$“.
- Pole (array, list) je uspořádaný kontejner skalárů indexovaný celými čísly 0, 1, 2 atd. Pole se symbolizují znakem „@“ a pro přístup k jejich prvkům se používá index (či seznam indexů) v hranatých závorkách „[]“. (Na rozdíl od GNU awk, v Perlu se prvky polí číslují vždy od nuly.) Výchozí hodnotou je prázdné pole.
- Asociativní pole (hash) je neuspořádaný kontejner skalárů (hodnot) indexovaný libovolnými řetězci (klíči). Symbolizuje se znakem „%“. Přístup k prvkům pole se vyznačuje použitím klíče (či seznamu klíčů) ve složených závorkách „{}“. Asociativní pole se inicializují poli či seznamy se sudým počtem prvků, kde se první prvek každé dvojice interpretuje jako klíč a druhý jako odpovídající hodnota. V seznamech se pak asociativní pole na takový seznam rozloží. Výchozí hodnotou je prázdné asociativní pole.
Je v pořádku mít vedle sebe proměnné „$x“, „@x“ a „%x“ a funkci „x()“, jsou to čtyři nezávislé věci. Konstanty však sdílejí „jmenný prostor“ s funkcemi.
- Ukazatel (reference, v češtině obvykle nazývaný „odkaz“) je skalár, který odkazuje na nějaký objekt v paměti (skalár, pole, funkci, regulární výraz atd.). Přístup k odkazovanému objektu se získává dereferencí ukazatele. Operace, při kterých ukazatel není výslovně dereferencován, se týkají ukazatele jako takového.
- Seznam je dočasný objekt příbuzný poli; zadává se výčtem prvků v kulatých závorkách, např. „(1, $b, 3)“. Kulaté závorky se nepoužijí, pokud je seznam bezprostředně obalen dalšími kulatými nebo hranatými závorkami. V téměř všech kontextech je seznam zaměnitelný s polem — kde se očekává pole, můžete uvést seznam, a naopak kde se očekává seznam, můžete uvést pole.
- Důležitou vlastností seznamů je zplošťování — když v seznamu uvedete vnořený seznam, pole nebo asociativní pole, to se obvykle rozvine na všechny svoje prvky v odpovídajícím pořadí, jako byste je uvedl/a přímo. Nespoléhejte se však na zplošťování při volání systémových a knihovních funkcí (může být ovlivněno tzv. prototypem funkce) a v seznamech stojících na levé straně operátoru přiřazení (tam funguje trochu jinak).
- Proud je objekt reprezentující soubor na disku nebo rouru vedoucí do jiného procesu. Umožňuje číst či zapisovat data, a to v textovém nebo binárním režimu.
- Řetězec bajtů je každý řetězec, který obsahuje jen znaky s kódovou hodnotou 0 až 255. Takový řetězec může být bez konverze zapsán do souboru v binárním režimu. Všechny řetězce načtené v binárním režimu jsou řetězce bajtů.
3. Zaklínadla: Základní
3/1 Proměnné a konstanty
3/2 Skaláry a undef
3/3 Volání funkcí
3/4 Definice funkcí
3/5 Komentáře
3/6 Volání příkazů /bin/sh
3/7 Operace s čísly
3/8 Speciální proměnné
4. Zaklínadla: Řízení toku
4/1 Podmínky
4/2 Cykly
4/3 Skoky
Poznámka k příkazům „last“, „next“ a „redo“: neoznačený blok příkazů „{}“ se v Perlu považuje za cyklus a tyto příkazy se na něj vztahují!
4/4 Přepínač typu switch
Poznámka: Perl nenabízí žádnou konstrukci, která by fungovala jako plnohodnotný přepínač s propadáním přes větve, použitím jedné větve pro více hodnot a větví „default“ a vynucovala konstantnost a jedinečnost hodnot pro jednotlivé větve. Nabízí sice několik možností, jak dosáhnout stejného chování, ale všechny kromě asociativního pole ukazatelů na funkce se vnitřně chovají jako sekvence if-else-if. Většina použití příkazu „switch“ však může být rozumně nahrazena inteligentním použitím asociativních polí.
5. Zaklínadla: Řetězce a regulární výrazy
5/1 Základní operace
5/2 Dělení na podřetězce
5/3 Literály řetězců
5/4 Literály regulárních výrazů
5/5 Najít (regulární výrazy a podřetězce)
Poznámka: funkce next_match_*() hledají shodu s regulárním výrazem v podřetězci vymezeném parametry „počáteční-index“ a „délka-hledání“ (jsou-li zadány); všechny indexy vracené těmito funkcemi jsou ale platné v původním prohledávaném řetězci. Pokud další shodu nenajdou, vrátí místo každého indexu či délky nehodnotu undef.
5/6 Najít a nahradit v řetězcové proměnné
5/7 Konverze čísel na řetězce a naopak
5/8 Heše
6. Zaklínadla: Pole
6/1 Literály (vytvořit pole z prvků)
6/2 Základní operace
6/3 Vkládání/vyjímání prvků
6/4 Filtrování
6/5 Transformace a zpracování pole
6/6 Řazení a přeskládání prvků v poli
Poznámka: volání funkce „sort“ nemůžete použít v kontextu, kde jsou viditelné vámi deklarované proměnné $a nebo $b. Proto se deklaraci takových proměnných vyhněte, nebo volání funkce „sort()“ odsuňte do samostatné funkce.
6/7 Vyhledávání a testování
7. Zaklínadla: Asociativní pole
7/1 Jako celek
7/2 Prvky
8. Zaklínadla: Ukazatelé
8/1 Ukazatelé obecně
8/2 Získat ukazatel
8/3 Dereferencovat ukazatel
8/4 Slabé ukazatele
9. Zaklínadla: Vstup/výstup
9/1 Otevřít/zavřít
9/2 Standardní výstup a chybová hlášení
9/3 Čtení (vstup) v textovém režimu
9/4 Zápis (výstup) v textovém režimu
9/5 Čtení (vstup) v binárním režimu
9/6 Zápis a ostatní operace v binárním režimu
9/7 Operace se soubory a pevnými a symbolickými odkazy
9/8 Operace s adresáři
9/9 Zjistit informace o adresářové položce
Poznámka: v případě, že funkce stat() selže, vrátí prázné pole; proto čtení jeho kteréhokoliv prvku vrátí undef. Mód a typ adresářové položky budou v takovém případě 0.
10. Parametry příkazů
'-Mkód' | Na začátek hlavního skriptu před čtením vloží příkaz „use kód;“ Toho je možné využít k připojení modulů, importu identifikátorů z nich, nastavení direktiv apod. Lze použít opakovaně. |
○ -0 ○ -0777 ◉ -0x0A ○ -0x017D | Nastavit $RS na: "\x{0}"/undef (celý soubor jako jeden záznam)/"\n"/"Ž" (uvádí se kód hexadecimálně). |
☐ -C0 | Vypne implicitní podporu Unicode. (Zatím jsem nezkoušel/a.) |
○ -n ○ -p | Režim připomínající GNU awk. Parametry skriptu jsou interpretovány jako cesty k souborům, které mají být čteny. Celý program se pak obalí do implictní smyčky, která z těchto souborů načítá záznamy ukončené $RS do proměnné $ARG. (Na rozdíl od GNU awk ukončovač záznamu není odebrán, k tomu je potřeba použít „chomp($ARG);“.) Hodnota $ARG se na konci každého cyklu: zahodí/vypíše. Tyto volby se obvykle používají v kombinaci s volbou -e, u delšího skriptu je totiž výhodnější čtecí cyklus napsat ručně. |
☐ -e 'skript' | Uvede skript na příkazové řádce namísto jeho čtení ze souboru. |
-I cesta | Vloží uvedenou cestu na začátek seznamu adresářů pro vyhledávání modulů (ekvivalent příkazu „use lib“ nebo parametru „'-Mlib("cesta")'“). Lze použít opakovaně. Seznam se prohledává od začátku, takže nově vložená cesta bude mít přednost před všemi předchozími. |
Varování: Nikdy do svých skriptů Perlu neuvádějte direktivu interpretu „#!“ (např. „#!/usr/bin/perl“)! Není snadné to udělat správně a neopatrné použití této direktivy může způsobit, že skript nepůjde spustit vůbec nebo se místo něj spustí něco úplně jiného.
11. Instalace na Ubuntu
Všechny použité nástroje jsou základními součástmi Ubuntu přítomnými i v minimální instalaci (jen balíček Linuxu: Knihy kouzel si musíte nainstalovat, aby vám fungoval spouštěč „lkk“ a aby byl dostupný modul LinuxKnihaKouzel.pm).
12. Ukázka
13. Tipy a zkušenosti
- Autovivifikace: Operátory („->[]“ a „->{}“) lze bezpečně použít i v případech, kdy na jejich levé straně stojí neexistující prvek asociativního pole či pole nebo neinicializovaná proměnná. Perl totiž hodnotu na levé straně zkontroluje, a pokud je undef, automaticky tam přiřadí ukazatel na nové, prázdné pole (resp. asociativní pole). Tato funkce se nazývá autovivifikace a výrazně usnadňuje práci s vnořenými asociativními poli. Dejte si ale pozor na skutečnost, že k ní dojde při každé dereferenci, nejen při takové, do které pak přiřazujete! To znamená, že i příkaz „delete $p->{"x"}“ způsobí, že se do $p (pokud je undef) přiřadí ukazatel na prázdné asociativní pole.
- Předávání parametrů do funkcí: Přiřaditelné skaláry se do funkcí předávají vždy odkazem; přiřazením do prvků zvláštního pole „@ARG“ lze přiřadit do skalárních proměnných, které byly předány funkci jako parametry. Pole se při předávání do funkce (pokud tomu nebrání její prototyp) rozloží na všechny svoje prvky v náležitém pořadí a ty se předají odkazem. Asociativní pole se rozloží na posloupnost dvojic „klíč,hodnota“, příčemž klíče se předají hodnotou (jsou nepřiřaditelné), zatímco hodnoty se předají odkazem. Perl neprovádí žádnou automatickou kontrolu počtu, typu či hodnoty předaných parametrů; ta je výhradně zodpovědností volané funkce. Je výhodné při ní použít funkci „typy()“ a regulární výraz.
- Vnořené datové struktury: Vnořené datové struktury se v Perlu realizují téměř výhradně pomocí ukazatelů. Příklad: my @vnořená_pole = ([1, 2], [3, 4]);
- print() a printf(): Dokumentace Perlu radí upřednostňovat funkci „print“ před „printf“, protože je rychlejší a snáze se píše. To první je nejspíš pravda, ale pokud ji chcete použít korektně, musíte mít kontrolu nad hodnotami globálních proměnných $OFS a $ORS, protože funkce „print“ je vypisuje, a budou-li nastaveny na nečekané hodnoty z jiné části programu, bude výstup vaší funkce nekorektní. Napsat "%s" do printf je obvykle mnohem jednodušší než neustále přiřazovat $OFS a $ORS.
- Funkce map(): Návratovou hodnotou posledního příkazu v bloku funkce „map()“ nemusí být skalár; může to být i seznam či pole. V takovém případě se jeho obsah do výsledného pole zploští, díky čemuž nemusí funkce map() vrátit stejný počet prvků jako obržela; může jich být víc i méně.
- Blok kódu: Blok kódu předávaný funkci jako zvláštní první parametr (což se týká především vestavěných funkcí grep(), map() a sort() nesmí obsahovat příkaz „return“, jinak tento příkaz ukončí obalující funkci a vrátí návratovou hodnotu z ní! To neplatí v případě, kdy se blok předává ukazatelem na anonymní funkci (s klíčovým slovem „sub“), tam je naopak příkaz „return“ vhodný.
- Správa paměti a slabé ukazatele: Správa paměti v Perlu je založená na počítání odkazů. Jakýkoliv objekt bude zrušen (včetně případného volání destruktoru) v momentě, kdy počítadlo odkazů na něj klesne na nulu. Slabí ukazatelé se do počtu odkazů nepočítají, a pokud bude objekt zrušen v době jejich existence, automaticky přitom získají nehodnotu undef. Podle dokumentace je slabost ukazatele typová vlastnost objektu, která se nekopíruje (jakákoliv kopie slabého ukazatele je opět silný odkaz) a přepíše se přiřazením, pokud nejde o přiřazení slabého ukazatele téže hodnoty.
13/1 Regulární výraz a řetězec náhrady
Uvnitř regulárních výrazů v Perlu můžete použít interpolaci skalární proměnné, např. takto:
Proměnná může obsahovat buď ukazatel na regulární výraz (ten se pak zakomponuje do nového regulárního výrazu), nebo textový řetězec – ten se za běhu interpretuje jako regulární výraz a také se zakomponuje.
Pokud proměnná obsahuje text a chcete ho vložit bez intepretace zvláštních znaků, použijte tento zvláštní druh interpolace do regulárního výrazu:
Uvnitř řetězců náhrady platí stejná pravidla odzvláštňování jako v řetězcových literálech obklopených dvojitými uvozovkami, až na to, že „"“ je obyčejný znak a „/“ je na místo toho zvláštní. Uvnitř řetězce náhrady můžete použít speciální proměnné $& (nahradí se za text shody) a $1, $2, ..., $9, ${10}, ... (nahradí se za text odpovídajícího záchytu). Také tam můžete použít interpolaci obyčejné proměnné, její text se použije doslova, bez interpretace zvláštních znaků.
14. Další zdroje informací
Poznámka č. 1: Pro spuštění příkazu „perldoc“ si musíte doinstalovat balíček „perl-doc“:
Poznámka č. 2: Webové tutorialy a oficiální dokumentace obsahují značné množství dalších konstrukcí, které v Linuxu: Knize kouzel nejsou zmíněny (např. operátor „<>“ nebo příkaz „given“). U řady z nich má jejich vynechání dobrý důvod a jejich použití může vést k nezamýšlenému chování programu, kterému budete moci porozumět jen po nastudování obrovského množství dokumentace v angličtině. Pokud se tomu chcete vyhnout, používejte jen jazykové konstrukce z kapitol Linuxu: Knihy kouzel.
- Wikipedie: Perl
- SATRAPA, Pavel. Perl pro zelenáče. 3. aktualizované a rozšířené vydání. Praha: CZ.NIC, z.s.p.o., 2018. CZ.NIC. ISBN 978-80-88168-35-5.
- Root.cz: seriál Perličky
- Kompletní oficiální dokumentace (anglicky — velmi dobrý zdroj)
- perldoc perlrun; perldoc perlvar; perldoc perlfunc; perldoc perlop (vše anglicky)
- YouTube: Perl Tutorial (anglicky)
- YouTube: Perl Online Training (anglicky)
- Oficiální stránka jazyka (anglicky)
- Balíček (anglicky)
- perltutorial.org (anglicky)
- Perl Tutorial for Beginners: Learn in 1 Day (anglicky)
- TL;DR: perl (anglicky)
15. Pomocné funkce a skripty
16. Zákulisí kapitoly
V této verzi kapitoly chybí:
- pack/unpack
- exec()
- zpracovat tutorial
Tato kapitola záměrně nepokrývá:
- nic