LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Perl (16) - Regulární výrazy - začínáme

Dneškem začíná v rámci seriálu Perl miniseriál o nesmírně mocném nástroji - regulárních výrazech.

19.10.2005 07:00 | Jiří Václavík | Články autora | přečteno 52123×

Regulární výrazy (anglicky regular expressions, někdy zkráceně označované jako regexp, regex nebo RE) jsou reprezentací regulárních jazyků v teorii konečných automatů.

Jejich aplikace (ve smyslu zda řetězce odpovídají vzoru) se poprvé objevila v unixových nástrojích pro editaci a vyhledávání v řetězcích - tedy sed, vi, grep, awk a další (více o historii například na Wikipedii). Nejsou mezi sebou úplně kompatibilní, protože většinou bylo k původním regulárním výrazům něco přidáno (potom tedy reprezentují nadmnožinu regulárních jazyků). V praxi se to projevuje tak, že to, co funguje awku, nemusí fungovat v grepu nebo může mít jinou syntaxi apod.

Mezi nástroje, které umí regulární výrazy se samozřejmě řadí i Perl. Jen těžko byste hledali jiný jazyk, který by podporoval regulární výrazy odpovídající tak silné množině jazyků. Navíc spojením kvalitního skriptovacího jazyka s regulárními výrazy získáváme do svého arzenálu nesmírně silný nástroj. Toto je jeden z hlavních důvodů, proč se Perl těší oblibě, kterou má. Proto ani zde nebudeme regulárními výrazy šetřit a pokusíme se je přiblížit opravdu podrobně.

Co je to regulární výraz?

Regulární výraz si můžeme představit jako speciální řetězec, který je šablonou vystihující určitý jazyk (tj. množinu textových řetězců). Každý textový řetězec takové šabloně buď vyhovuje nebo ne. S touto množinou vyhovujících řetězců můžeme manipulovat - hledat její prvky v textu nebo je nahrazovat jiným řetězcem.

Vzpomeňme si, že jsme na regulární výrazy již natrefili při popisu funkcí grep a split. To jsme ale jen uvedli příklady a dále je nerozebírali.

Formální definice regulárních výrazů

Nechť X = {x1, ..., xn} je nějaká konečná neprázdná abeceda a l označuje prázdné slovo. Pak množinou všech regulárních výrazů RE(X) nad abecedou X je nejmenší množina slov v abecedě {x1, ..., xn, {}, l, *, +, ., (, )}, pro kterou platí:

  • RE(X) obsahuje každý prvek abecedy X, dále pak l a {}
  • Jsou-li r, s v RE(X), pak je tam i r+s a r.s
  • Je-li r v RE(X), pak je tam i r*

Regulárním výrazem tedy je například (((a*((b+c).d)*)+e)*f). Některé závorky a tečky lze po dohodě vynechat a můžeme psát ((a*(b+cd)*)+e)*f.

Hodnotou regulárního výrazu r je jazyk L = [r], pro který platí:

  • [{}] = {}
  • [l] = {l}
  • [x] = {x} pro všechna písmena z abecedy X
  • [(r+s)] = [r] sjednoceno s [s]
  • [(r.s)] = [r] . [s]
  • [r*] = [r]*

Regulární výrazy odpovídají regulárním jazykům. Regulární výrazy v Perlu jsou nadmnožinou formální definice. Třeba proto, že obsahují i jazyk L = {0n1n}, který regulární není. Ačkoliv to není formálně v pořádku, budeme je nazývat regulárními výrazy i nadále.

Regulární výrazy versus žolíkové znaky

Regulární výrazy jsou někdy zaměňovány se žolíkovými znaky. Obecně, žolíkový znak může vyhovovat jednomu nebo více znakům. Oproti tomu regulární výraz je řetězec s jasně určenými podmínkami a žádný samotný znak zde nezastupuje více znaků. Například * v žolíkových znacích znamená libovolný řetězec, ale v regulárních výrazech libovolný počet opakování. Žolíkové znaky se používají téměř výhradně k hledání v názvech souborů.

Regulární výrazy v Perlu

Základní syntaxe

Regulární výraz (od teď již jen v perlové terminologii) je výraz, který má dvě možné vyhodnocení - buď true nebo false. To znamená, že následující zápis vrací 1, pokud se v řetězci vyskytuje podřetězec "vzor", v opačném případě prázdný řetězec.

"řetězec" =~ m/vzor/

Regulárnímu výrazu m/vzor/ vyhoví takové řetězce jako "vzory", "re vzor" nebo "vzor". Operátor =~ slouží k porovnávání vzorů. S přiřazováním má společný opravdu jen ten znak rovnítka, jinak jde o odlišné operace.

Následující díly seriálu se tedy budou věnovat prakticky pouze tomu, co napsat místo vzoru, abychom vytvořili požadovanou šablonu. Dodejme, že v Perlu 6 dojde ke kompletnímu přepracování regulárních výrazů a už nepůjde jen o úpravu jednoho řetězce. Budou mít podstatně intuitivnější strukturu, více integrované do jazyka a navíc ještě o něco silnější.

Další možná uvození

Uvozující m není povinné, navíc můžeme stejně jako u nám už známých q a qq lomítka nahradit jiným znakem. Negovaný operátor =~ se zapisuje jako !~.

print "řetězec" =~ m"vzor";
print "řetězec" =~ m!vzor!;
print "řetězec" =~ /vzor/; #nejběžnější užití
print "řetězec" !~ /vzor/;

Existuje několik speciálních ohraničení pro regulární výrazy. Použijí-li se apostrofy, neprobíhá vkládání obsahu proměnných. Nelze tedy psát:

$vzor = "[abc]{2}";
"aa" =~ m'$vzor'; #$vzor není nahrazen obsahem proměnné, ale je brán jako řetězec '$vzor'

Další možností je ohraničení otazníky (potom uvedení m není povinné). V takovém případě dojde k použití vzoru pouze jednou (i v testu cyklu s modifikátorem g). Teprve až je zavolána funkce reset, může se porovnání opakovat. Tuto konstrukci uvádíme pouze pro zajímavost a nelze ji doporučovat. My se budeme striktně držet používání lomítek.

Užití v testech podmínek

Porovnávání řetězců se užívá jako test při rozhodování.

$veta = "Existuje 10 druhů lidí - ti, kteří znají binární kód, a ti, kteří ne.";

if ($veta =~ m/10 druhů/){
    print "'10 druhů' je ve větě!\n"
}

if ($veta =~ m/777/){
    print "'777' je ve větě!\n"
}

"10 druhů" se v řetězci vyskytuje, proto byl v tomto případě výraz vyhodnocen jako true. Nezáleží na tom na jaké pozici nebo co je okolo.

Použití výchozí proměnné

Je také možné uvést jako test podmínky jen čistě regulární výraz v uvozovacích znacích. Implicitně je porovnáván s výchozí proměnnou. Příklad má stejný účinek jako předchozí, ale využívá této vlastnosti:

$_ = "Existuje 10 druhů lidí - ti, kteří znají binární kód, a ti, kteří ne.";

if (/existuje/){
    print "'existuje' je ve větě!\n"
}

if (/Existuje/){
    print "'Existuje' je ve větě!\n"
}

Poslední ukázka tiskne řetězec "'Existuje' je ve větě!". Na velikosti písmen tedy implicitně záleží. Způsob, kterým lze toto chování změnit, si představíme v jednom z příštích dílů.

V případě zkráceného zápisu pomocí výchozí proměnné je též možné negovat. Stačí přidat vykřičník před úvodní /.

if (!/2 druhy/){
    print "'2 druhy' není ve větě!\n"
}

Metaznaky

Mezi lomítka lze napsat všechny znaky znaky kromě takzvaných metaznaků. Mají totiž nějakou jinou funkci. Patří mezi ně *, +, ., ?, ^, $, (, ), {, }, [, ], |, /. Lze je nahradit předřazením zpětného lomítka. Pokud si nejste jisti, zda má znak speciální význam a není alfanumerický (tedy pokud je z množiny \W), můžeme mu předřadit zpětné lomítko vždy. Sekvence zpětného lomítka a nealfanumerického znaku se chová vždy jako znak bez speciálního významu.

Proměnné v regulárních výrazech

Než se začne regulární výraz vyhodnocovat, jsou nahrazeny proměnné ve vzoru svým obsahem (což ale samozřejmě neplatí u ohraničení pomocí apostrofů).

$cisla = "2005";
print "0002005000" =~ /$cisla/;

Druhý řádek předchozího kódu bude fungovat takto:

print "0002005000" =~ /2005/;

Návratová hodnota výrazu řetězec =~ vzor

Tuto část lze zatím klidně přeskočit, protože je zde řada věcí, které jsme zatím neprobírali. Je to ale téma, které by v prvním dílu o regulárních výrazech chybět nemělo.

skalární kontext

Ve skalárním kontextu vrací v případě úspěchu 1, v případě neúspěchu nepravdivou hodnotu.

seznamový kontext

O něco složitější je to v seznamovém kontextu. Při neúspěchu bez modifikátoru g vrací prázdný seznam. V případě úspěchu vrací seznam zapamatovaných hodnot, pokud jsou, jinak vrací seznam (1). S modifikátorem g vrací výraz pole vyhovujících podřetězců.

$retezec = "12345";
@return1 = $retezec =~ /\d\d\d/;
@return2 = $retezec =~ /(\d)(\d)(\d)/;
@return3 = $retezec =~ /(\d)/g;

Pole @return1 obsahuje prvek (1). Žádná hodnota nebyla zapamatovaná. Oproti tomu v poli @return2 už takové hodnoty byly: jeho prvky (1, 2, 3) jsou právě zapamatovanými hodnotami. Poslední pole obsahuje (1, 2, 3, 4, 5), protože se vzor aplikoval celkem 5×.

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

15.4.2017 15:20 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě IoT a radiokomunikace? Přijď na sraz spolku OpenAlt, který se bude konat ve středu 19. dubna od 18:30 v Šenkovně (Sokolská 60, Praha 2).
Přidat komentář

5.3.2017 19:12 /Redakce Linuxsoft.cz
PR: 23. března proběhne v Praze konferenci na téma Cloud computing v praxi. Hlavními tématy jsou: Nejžhavější trendy v oblasti cloudu a cloudových řešení, Moderní cloudové služby, Infrastruktura současných cloudů, Efektivní využití cloudu, Nástrahy cloudových řešení a jak se jim vyhnout.
Přidat komentář

27.2.2017 22:12 /František Kučera
Pozvánka na 137. sraz OpenAlt – Praha: Tentokrát jsme si pro vás připravili neobvyklou akci. Ve středu 1.3. v 17:30 nás přivítá sdružení CZ.NIC ve svých prostorách v Milešovské ulici číslo 5 na Praze 3, kde si pro nás připravili krátkou prezentaci jejich činnosti. Následně navštívíme jejich datacentrum pod Žižkovskou věží. Provedou nás prostory, které jsou běžnému smrtelníkovi nedostupné!
Po ukončení prohlídky se všchni odebereme do hostince U vodoucha, Jagelonská 21, Praha 3 pochutnat si na některém z vybraných piv či dát si něco na zub. Rezervaci máme od 19:30, heslo je OpenAlt.
Ale pozor! Do prostor datového centra máme omezený přístup, dostane se tam pouze 10 lidí! Takže kdo přijde dříve, ten má přednost, a občanky s sebou! Kdo nebude chtít na prohlídku datového centra, může se pomalu přesunout do hostince U vodoucha a u nepřeberné nabídky piv počkat na ostatní.
Přidat komentář

18.1.2017 0:49 /František Kučera
Členové a příznivci spolku OpenAlt se pravidelně schází v Praze a Brně. Fotky z pražských srazů za uplynulý rok si můžete prohlédnout na stránkách spolku. Příští sraz se koná už 19. ledna – tentokrát je tématem ergonomie ovládání počítače – tzn. klávesnice, myši a další zařízení. Také budete mít příležitost si prohlédnout pražský hackerspace Brmlab.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

15.6.2017 9:34 / Ondřej Havlas
php,

10.6.2017 10:39 / Temple
sell home for cash

11.5.2017 23:32 / lelo
Re: Problém se správcem balíčků

11.5.2017 5:45 / davd mašek
Re: Problém se správcem balíčků

10.5.2017 22:54 / lelo
Re: Problém se správcem balíčků

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze