Perl – rychlá reference

Praktický tahák k syntaxi, regulárním výrazům, souborům, funkcím a objektům. Příklady počítají s moderním Perlem 5.

1. Začínáme

Soubor uložte například jako program.pl a spusťte příkazem perl program.pl.

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';

say "Ahoj, světe!";
Doporučení: strict odhaluje problematický kód, warnings upozorňuje na chyby a say automaticky přidává nový řádek.

2. Proměnné a datové typy

SigilTypPříklad
$skalár – číslo, text nebo referencemy $vek = 25;
@polemy @barvy = ('červená', 'modrá');
%hash – dvojice klíč/hodnotamy %uzivatel = (jmeno => 'Eva');
my $jmeno = "Anna";
my $vek   = 30;
my $text  = "$jmeno má $vek let";  # interpolace
my $doslova = '$jmeno';             # bez interpolace

my $nedefinovano;
say defined $nedefinovano ? "má hodnotu" : "undef";

Proměnné deklarujte pomocí my. Perl dynamicky převádí text a čísla podle kontextu.

3. Operátory

Čísla

+ - * / % **

my $vysledek = (10 + 2) * 3;
my $mocnina = 2 ** 8;

Text

. spojuje, x opakuje

my $cele = "Per" . "l";
say "-" x 20;

Porovnání

Čísla: == != < > <= >= <=>
Text: eq ne lt gt le ge cmp

say "shoda" if $jmeno eq "Anna";
say "větší" if $vek > 18;

Logika

&& || ! nebo and or not

if ($vek >= 18 && $aktivni) {
    say "povoleno";
}

4. Podmínky a cykly

if / elsif / else

if ($vek < 18) {
    say "nezletilý";
} elsif ($vek < 65) {
    say "dospělý";
} else {
    say "senior";
}

say "aktivní" unless !$aktivni;

Cykly

for my $i (1..5) {
    say $i;
}

for my $barva (@barvy) {
    say uc $barva;
}

while ($pocet > 0) {
    $pocet--;
}

V cyklu lze použít next (další iterace), last (ukončení) a redo (opakování aktuální iterace).

5. Pole a hashe

Pole

my @ovoce = qw(jablko hruška švestka);
say $ovoce[0];

push @ovoce, 'banán';
my $posledni = pop @ovoce;
my $prvni    = shift @ovoce;
unshift @ovoce, 'mango';

my @serazene = sort @ovoce;
my @delky = map { length $_ } @ovoce;
my @dlouhe = grep { length($_) > 5 } @ovoce;

Hash

my %osoba = (
    jmeno => 'Karel',
    vek   => 42,
);

say $osoba{jmeno};
$osoba{mesto} = 'Brno';
delete $osoba{vek};

for my $klic (sort keys %osoba) {
    say "$klic: $osoba{$klic}";
}

Reference a vnořené struktury

my $data = {
    jmeno  => 'Jana',
    jazyky => ['Perl', 'Python'],
    adresa => { mesto => 'Praha', psc => '11000' },
};

say $data->{jmeno};
say $data->{jazyky}[0];
say $data->{adresa}{mesto};

6. Regulární výrazy

my $text = "Kontakt: eva@example.cz";

if ($text =~ /([\w.+-]+)@([\w.-]+)/) {
    say "Uživatel: $1, doména: $2";
}

$text =~ s/Kontakt/E-mail/;        # první náhrada
$text =~ s/[aeiouy]/_/gi;          # všechny, bez ohledu na velikost
my @slova = split /\s+/, $text;
my $radek = join ', ', @slova;
PrvekVýznam
. \d \w \slibovolný znak; číslice; znak slova; bílý znak
* + ? {n,m}0+; 1+; volitelně; počet opakování
^ $ \bzačátek; konec; hranice slova
(...) (?:...) [abc]zachycení; skupina bez zachycení; množina znaků
/i /g /m /s /xbez velikosti; globálně; více řádků; tečka i nový řádek; čitelný zápis

7. Funkce (subrutiny)

sub secti {
    my ($a, $b) = @_;
    return $a + $b;
}

say secti(2, 3);

# Signatury v moderním Perlu
use feature 'signatures';
no warnings 'experimental::signatures'; # podle verze Perlu

sub pozdrav($jmeno, $pozdrav = 'Ahoj') {
    return "$pozdrav, $jmeno!";
}

Argumenty běžně přicházejí v poli @_. Poslední výraz se vrací automaticky, explicitní return však často zvyšuje čitelnost.

8. Soubory a vstup/výstup

use open qw(:std :encoding(UTF-8));

open my $in, '<', 'vstup.txt'
    or die "Nelze otevřít vstup.txt: $!";

while (my $radek = <$in>) {
    chomp $radek;
    say "Čtu: $radek";
}
close $in;

open my $out, '>', 'vystup.txt'
    or die "Nelze zapsat: $!";
print {$out} "První řádek\n";
close $out;

Režimy: < čtení, > přepsání, >> přidání, +< čtení i zápis. Proměnná $! obsahuje systémovou chybu.

Argumenty příkazové řádky

my ($soubor, @zbytek) = @ARGV;
die "Použití: $0 SOUBOR\n" unless defined $soubor;

9. Moduly, JSON a chyby

# Vestavěný/praktický modul
use Path::Tiny;
my $obsah = path('data.txt')->slurp_utf8;

# JSON::PP je součástí jádra Perlu
use JSON::PP qw(encode_json decode_json);
my $json = encode_json({ stav => 'ok', pocet => 3 });
my $data = decode_json($json);

# Zachycení chyby
eval {
    die "Něco se pokazilo";
};
warn "Chyba: $@" if $@;

Moduly z CPAN lze instalovat například pomocí cpanm Nazev::Modulu. Dostupnost nástroje závisí na instalaci Perlu.

10. Jednoduchý objekt

package Osoba;
use strict;
use warnings;

sub new {
    my ($class, %args) = @_;
    return bless {
        jmeno => $args{jmeno} // 'Neznámý',
        vek   => $args{vek}   // 0,
    }, $class;
}

sub popis {
    my ($self) = @_;
    return "$self->{jmeno} ($self->{vek})";
}

package main;
my $osoba = Osoba->new(jmeno => 'Eva', vek => 28);
say $osoba->popis;

Pro větší projekty se často používají objektové systémy z CPAN, například Moo nebo Moose.

11. Užitečné vestavěné funkce

FunkcePříklad / účel
chompodstraní koncový oddělovač řádku
length, substrdélka a část textu
lc, ucmalá a velká písmena
sprintfsprintf '%.2f', 3.14159
int, rand, abscelá část, náhodné číslo, absolutní hodnota
localtime, timemístní čas a Unix timestamp
exists, definedexistence klíče a definovanost hodnoty
die, warnukončení s chybou a varování

Mini příklad: četnost slov

use strict;
use warnings;
use feature 'say';
use open qw(:std :encoding(UTF-8));

my %cetnost;
while (my $radek = <STDIN>) {
    $cetnost{lc $1}++ while $radek =~ /([[:alpha:]]+)/g;
}

for my $slovo (sort { $cetnost{$b} <=> $cetnost{$a} } keys %cetnost) {
    say "$slovo\t$cetnost{$slovo}";
}

Spuštění: perl cetnost.pl < text.txt