170 likes | 273 Views
Regular expression engine 1.pravidlo. Reg. výraz je snaživý. Snaží se vyhovět co nejdelším řetězcem. Zahrnuje další a další znaky, jak to jen dlouho jde. Teprve tehdy, když narazí na něco, co zadané formě (regulárnímu výrazu) nevyhovuje, přestane se snažit. /a*/.
E N D
Regular expression engine 1.pravidlo Reg. výraz je snaživý. Snaží se vyhovět co nejdelším řetězcem. Zahrnuje další a další znaky, jak to jen dlouho jde. Teprve tehdy, když narazí na něco, co zadané formě (regulárnímu výrazu) nevyhovuje, přestane se snažit. /a*/ Vyhovuje vždy (minimálně jako prázdný řetězec).
Regular expression engine 2.pravidlo Regulární výraz je pilný. Začíná pracovat hned, jakmile to jde, tedy od prvního písmene zadaného řetězce. Zkouší to tak dlouho, až • buď něco pasuje, • nebo narazí na konec řetězce /\w+/ Vydá první slovo, i kdyby to bylo třeba jen číslo řádku.
Regular expression engine 3.pravidlo Regulární výraz je hladový a lakomý. Operátory + a * „sežerou“, co se dá. Jestliže zbytek regulárního výrazu nepasuje se zbytkem řetězce, stroj pouští jeden znak po druhém, až to • buď pasuje, • nebo musí pustit všechno, co nahrabal. Napasuje se na celou řádku a teprve potom ukrajuje z konce, aby vyhověl druhé části reg. výrazu. /.*\d\./
Regular expression engine 4.pravidlo Regulární výraz se nerad rozhoduje. Jestliže existují dvě větve, vždycky vybere tu první, i kdyby ta druhá vydala delší vyhovující řetězec. Vybere si první možnost od začátku. V $1 bude tedy |m|, nikoli |motiva|. /o(m|m\w+)/ lokomotiva
Zpětný odkaz – opakování • Co je v závorce, uloží se při shodě do speciální proměnné, na kterou se odkazuje pomocí \N, kde N je pořadí levé závorky v reg. výrazu Co vyhovuje těmto reg. výrazům? /^[^aeiouy]*([aeiouy])[^aeiouy]+\1[^aeiouy]?$/ /([^aeiouy])([aeiouy]).*\1\2.*/ • To, co vyhovovalo reg. výrazu v závorce, se nadále uchovává ve spec. proměnných $1, $2, ... • S těmito proměnnými lze pracovat i ve zbytku programu.
Zpětný odkaz – pokročilé pokračování Když ho nepotřebujeme, je lepší ho nevytvářet Text +9457 -9457 9457 +9457 $1 + - undef + $2 9457 9457 9457 9457 /(\s*[-+])?(\d+)/ První odkaz nepotřebujeme uchovávat, ale závorka se nám hodí. $1 9457 $2 Nevytvoří se /(?:\s*[-+])?(\d+)/
Asociativní pole - hash • Další typ proměnné • Zatím známe • skaláry • pole • hash = něco podobného jako pole, ale k indexování lze použít cokoli, ne nutně přirozené číslo • Název - stejná pravidla jako pro název skaláru nebo pole • Uvozovací znak je % • %h, $h, @h jsou naprosto různé věci, které nemají vůbec nic společného, ale nevyužívejme toho!
Vytvoření • Na první pohled obyčejný seznam, ale interpretuje se po dvojicích. 1. člen dvojice - tzv. klíč - musí být jednoznačný !! 2. člen dvojice - jeho hodnota • Způsoby zápisu (liché x sudé prvky "pole"): %tel_seznam=("Petr",2434,"Pavel",2478,"Monika",3482); %tel_seznam=qw(Petr 2434 Pavel 2478 Monika 3482); %tel_seznam= ( Petr=>2434, Pavel=>2434, Monika=>3482);
Přístup k jednotlivým prvkům hashe • Klíč se může, ale nemusí psát v uvozovkách • Přiřazování nového prvku: $tel_seznam{"Lucie"} = 9434; • Výpis existujícího prvku: print "Petr má telefonní číslo $tel_cislo{Petr}.\n"; • Vymazání prvku - funkce delete - výsledek je hodnota příslušná k zadanému klíči my$monika =delete $tel_seznam{Monika}; • Více prvků najednou my @vic_cisel = @tel_seznam{"Petr","Lucie");
Funkce keys • Vydá seznam všech klíčů • Pořadí je "náhodné" • Lze procházet v cyklu: foreach $jmeno (keys %tel_seznam) { print "$jmeno\t$tel_seznam{$jmeno}\n"; }
Funkce values • Podobná jako keys, ale výsledkem jsou ne klíče, nýbrž hodnoty • Pořadí stejné jako u keys, tedy pro nás náhodné. my @cisla = values %tel_seznam; print "Telefonní čísla v našem ústavu jsou @cisla.\n"; Skrz hodnoty ale nemáme přístup ke klíčům.
Prohození klíčů a hodnot • Asociativní pole lze přiřadit do normálního pole @cisla = %tel_seznam; • Pořadí prvků v poli obrátíme pomocí funkce reverse: (Pořadí prvků není známé, ale důležité je, že se prohodí lichá a sudá místa.) @r_cisla = reverse (@cisla); • Pole nyní můžeme přiřadit zpět do asociativního pole - • liché prvky se budou interpretovat jako klíče • sudé ------------"------------------ hodnoty %lidi = @r_cisla; Na něco si přitom musíme dát pozor ! Na co ?
Funkce each • Vydá dvouprvkový seznam (klíč, příslušná hodnota) • Zapamatuje si, kde skončila, a příště vydá další dvojici z hashe • Po projití celého hashe vydá prázdný seznam • Pořadí je opět náhodné (stejné jako u funkcí keys a values) Př. na výpis celého hashe: while(($jmeno, $cislo) = each(%tel_seznam)) { print "$jmeno má tel. číslo $cislo.\n"; }
Pole x hash • Mohli bychom všechno udělat pomocí pole, ale bylo by to • složitější na programování • pomalejší • Nemusíme (nemůžeme) se starat o uspořádání • Hash ve skalárním kontextu má nepoužitelnou hodnotu (neexistuje nic podobného k $#pole). Počet prvků hashe se musí spočítat.
Třídění polí - funkce sort • Třídí pole lexikograficky @jmena = qw/Petr Vašek Pavla Nikolaj Daniel Cyril/; @jmena_s = sort @jmena; • Ale @cisla = (23,3,15,203); @cisla_s = sort @cisla; print "@cisla_s\n"; # co se vypíše? • Jak na to? @cisla_s = sort {$a<=>$b} @cisla; @cisla_r = sort {$b<=>$a} @cisla; # opačné pořadí
Co dělá následující program? Napište k němu komentáře. A najděte chyby. #!/usr/bin/perl use locale; open(V, $ARGV[0]) or die "Nelze otevrit $ARGV[0]\n"; my %frek; my @slova; my $s; my $klic; while(<V>) { chomp; @slova = split(/[\s\W],$_); foreach $s (@slova) {$frek{$s}++;} } foreach $klic (sort keys %frek) {print VYSTUP "$klic $frek{$klic}\n";} }
Další možné využití hashe • Kontrola klíčových slov my %konce = (konec=>1,exit=>1,stop=>1, leave=>1,quit=>1); while(1) { print "Napiš nějaký vstup, nebo jestli se má skončit: "; $codal = <STDIN>; chomp $codal; if($konce{lc($codal)}) {print "Končíme.\n";last} else {print "Nekončíme, jedeme dál.\n"} }