Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Regulární výrazy v příkladech

Nevíte, co je regulární výraz? Rádi byste si regulární výrazy vyzkoušeli? Zajímá vás, jak takový regulární výraz vypadá uvnitř? Děsí vás slovo automat? Pak je tento článek určen právě vám.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Regulární výrazy nám umožňují jednoduše vyhledávat a nahrazovat text. Pronikly snad do všech programů pro zpracování textů. V dnešní době nenajdete v Linuxu textový editor, který by regulární výrazy nepodporoval. Pro ty, kteří si nedokážou regulární výraz vůbec představit, bych zde uvedl jednoduché přirovnání k „zástupným žolíkům“ u vyhledávání souborů. Pokud o regulárních výrazech vůbec nic nevíte, doporučuji si přečíst skvělý seriál, který vyšel na rootu.

Začneme netradičně. Povíme si něco o tom, jak počítač regulární výrazy vyhodnocuje. Ze všeho nejdříve si pro něj sestaví konečný(nejlépe deterministický, aby se dobral výsledku) automat. Automat je věc, do které pošlete řetězec a ona rozhodne, zda daný vstup výrazu vyhovuje, či ne. Je to taková černá skříňka. Automaty obvykle znázorňujeme jako orientované grafy, kde uzly jsou stavy automatu a (orientované) hrany představují přechody mezi nimi. Některé uzly zvolíme jako koncové (např. barevně je odlišíme). Po vytvoření se automat inicializuje, to znamená, že přejde do počátečního stavu (obykle je označen q0). Automat pracuje po krocích. V každém kroku načte jeden znak ze vstupu, což je dáno právě regulárností výrazu. Pokud ze stavu existuje přechod odpovídající načtenému znaku, automat přejde do nového stavu a pokračuje dalším znakem. V opačném případě se znova inicializuje a načte další znak. Opakuje to tak dlouho, dokud daný vstup celý nenačte (záleží na regulárním výrazu, můžete také definovat, aby při prvním selhání ukončil činnost) nebo neskončí v koncovém stavu. Pokud ano, vstup je rozpoznán.

Celou věc si nyní ukážeme na příkladu. Uvažujme následující jednoduchý regulární výraz: www\.[a-z]*\.(cz|sk). Pro tento výraz by počítač sestavil podobný automat, jaký vidíte na obrázku.

Automat

Samozřejmě, že si počítač nesestaví orientovaný graf. Nejjednodušší je pro něj stavy očíslovat, do aktuálního stavu uložit nulu a sestavit si matici přechodů (např. pomocí dvojrozměrného pole). Uvažujme nyní vstup www.root.cz. Automat se nachází ve stavu q0. Načte znak „w“, pro něj existuje přechod do stavu q1. Automat tedy načte znovu (2×) znak „w“, až se dostane do stavu q3, kde načte tečku, čímž se podobným způsobem dostane až do stavu q4. Zde se odehraje tzv. uzávěr. Automat načte znak „r“. Pro něj ale existuje přechod ([a-z] je zkráceně zapsáno {a, b, c, …, y, z}). Je to dokonce přechod q4 na q4 (v odborné hantýrce tzv. kvedlání :-). Tento proces se opakuje (automat vykvedlá) až po znak „t“. Nyní je na programu druhá tečka, která zapříčiní přesunutí do stavu q5. Ve stavu q5 akceptuje znak c nebo s, to díky speciálním znakům )|( – proč jsem závorky v tomto textu zaměnil, je asi každému ;-] jasné. Pokud vše dobře dopadne (jako že ano), tak se dostane až do stavu q8. Tento stav jsme zvolili jako koncový, tutíž automat akceptuje vstup. Zkuste akceptovat tuto větu: „www.microsof­t.com“. Podle mého názoru automat takto zkonstruovaný takové zadání neakceptuje (a nejen on ;-).

Jistě chápete, proč jsou regulární výrazy tak mocné. Jednak lze s nimi pokrýt širokou paletu gramatik a jednak jsou poměrně rychlé. Přehazovat někde ukazatel nebo přesouvat číslo z paměti do registru, no tak to by totiž počítači šlo (jak říká jeden můj kamarád – počítačův sen). Na druhou stranu na jiné gramatiky (např. bezkontextové) již regulární výraz nestačí. Snadno lze dokázat, že nelze sestavit regulární gramatiku, která by akceptovala například vstup ve tvaru 011010…1100 (se stejným počtem jedniček a nul, tedy vstup 100 už ne) nebo která by ověřovala paritu závorek.

Když už víme, jak regulární výraz funguje a na co je, můžeme začít experimentovat. Implementací regulárních výrazů je mnoho. Nejznámější z nich jsou asi implementace Perl5+, AWK, vim nebo GNU grep. My se v našem povídání zaměříme na implementaci Perl5+, což je de facto standard, který používá nejen programovací jazyk Perl verze 5 nebo vyšší. Většinu řídících výrazů však mají všechny implementace společné a liší se jen drobnostmi.

Pokud nějaký řetězec vyhovuje naší podmínce, můžeme ho prostě jen zobrazit (různe vyhledávací programy typu grep, egrep), získat na něj odkaz, či ho modifikovat (v programovacích jazycích, jako je Perl a podobně). Pokud váš oblíbený jazyk nepodporuje regulární výrazy (v dokumentaci hledejte slovo „regexp“), tak si můžete z internetu stáhnout knihovnu, pomocí které s nimi můžete snadno pracovat i v těchto jazycích (např. C/C++). Jazyků, které regulární výrazy přímo podporují, je ale mnoho, jmenujme alespoň Perl, Python, Ruby, Java či C#. Podívejme se nyní na význam nejdůležitějších řídících výrazů:

Tabulka č. 366

Výraz

Vysvětlení

Znaky
x znak x
\\ zpětné lomítko
\0n znak v osmičkovém kódu 0n (0 <= n <= 7)
\xhh znak v hexadecimálním kódu 0×hh
\uhhhh znak UNICODE v hexadecimálním kódu 0×hhhh
\t znak tabulátor (‚\u0009‘)
\n znak nového řádku (‚\u000A‘)
\r znak posunu vozíku (‚\u000D‘)
Skupiny znaků
[abc] výčet znaků: a, b, nebo c
[^abc] jakýkoli znak kromě: a, b, nebo c(negace)
[a-zA-Z] a až z nebo A až Z, včetně (rozsah)
[a-d[m-p]] a až d, nebo m až p: [a-dm-p](sjednocení)
[a-z&&[def]] d, e, nebo f (průnik)
[a-z&&[^bc]] a až z, kromě b ac: [ad-z](rozdíl)
Předdefinované skupiny znaků
\d číslice: [0–9]
\D opak číslice (negace): [^0–9]
\s bílý znak: [ \t\n\x0B\f\r]
\S opak bílého znaku: [^\s]
\w slovo: [a-zA-Z0-9]
\W opak slova: [^\w]
Hranice
^ začátek řádku
$ konec řádku
\b hranice slova
\B opak hranice slova (negace)
Kvantifikátory
X? X, žádný nebo jeden
X* X, žádný nebo více
X+ X, jeden nebo více
X{n} X, přesně nkrát
X{n,} X, minimálně nkrát
X{n,m} X, minimálně nkrát, ale ne více než mkrát
Logické spojky
XY X ihned zaY
X|Y X neboY
(X)

párování logických spojek
slouží také k zapamatování při nahrazování pomocí \1 až \\n/p>

Nyní si všechno vyzkoušíme. Všechny zde uvedené příklady můžete ihned zkoušet v apletu. Pro běh apletu budete potřebovat plug-in Java 1.3 nebo vyšší.

Příklad: pro
Vyhledali jsme všechny výskyty řetězce pro. Žádná věda. Jdeme dál.

Příklad: .e
Vyhledáme všechny řetězce, které začínají libovolným znakem (řídící znak tečka) a pokračují znakem e. Jejich délka musí být přesně 2.

Příklad: .*1
V podobném příkladě však použijeme kvantifikátor hvězdička, který říká, že před číslem 1 musí být žádný nebo více libovolných znaků. Všimněte si, že regulární výraz se chová „hladově“ a snaží se maximalizovat výsledek. V tomto případě pohltil celé zadání až po poslední jedničku v textu. „Hladovost“ se dá v regulárních výrazech omezovat, ale to se v různých implementacích li­ší.

Příklad: \bpro\b
V tomto případě jsme využili hranici slova a vyhledali pouze slova „pro“ stojící samostatně.

Příklad: \b(a|i|o|u)\b
Pomocí tohoto zadání vyhledáme konkrétní předložky a spojky. Pomocí logického NEBO a díky závorkám jsme efektivně definovali, které to mají být.

Příklad: \d+\.\d+\.\d+\­.\d+
Regulární výraz vyhledá všechny IP adresy v textu. Pomocí \d+ jsme určili jednu nebo více cifer. Tečka je speciální znak, proto jí musí předcházet zpětné lomítko (\.).

Příklad: (\d{1,3}\.){3}\d{1,3}
Příklad se stejným výsledkem, ale napsaný jinak. V tomto případě se na IP adresu díváme jako na tři po sobě jdoucí cifry délky 1 až 3, vždy následované tečkou. Za poslední číslicí však již tečka není, a tak jsme ji zahrnuli do výrazu zvlášť.

Příklad: http://[a-zA-Z_.]+
Tímto výrazem můžeme snadno nalézt webové odkazy. Jistě byste už dovedli zkonstruovat odkaz, který by například našel jen ty odkazy, které by nekončily řetězcem „asp“.

TIB2012

       

Příklad: (http://)?w{3}[a-zA-Z_.]+\.cz
Složitější příklad, ve kterém říkáme, že adresa může začínat řetězcem „http://“ (ale nemusí: otazník znamená „žádný nebo jeden“), následuje „www“, pak znaky a-Z, podtržítko a tečka a vše to končí řetězcem „.cz“. Jedná se o vyhledání URL v české doméně začínající „www“.

Příklad: [a-zA-Z_.]+@[a-zA-Z_.]+
Poslední příklad je jednoduchý regulární výraz pro vyhledání e-mailové adresy. Jak jistě víte, e-mailová adresa může mít mnoho podob, díky speciálním znakům můžeme nadefinovat, přes jaké servery má být dopis doručen, dokonce se dá posílat i na číselné adresy a podobně. Takový regulární výraz by však byl značně složitý (viz příklad v knize Mastering regular expresions, O`Reilly, který má i s komentářem několik stran). My se spokojíme s tím, že adresa je tvaru „něco před znakem at (@) a něco za ním“.

Školení: IP v 6 na Linuxu

Tento krátký kurz je určený speciálně pro zkušené správce sítí IPv4, kteří se chtějí seznámit s nastupujícím internetovým protokolem IPv6.

Platforma: Linux

  • Adresace
  • Link-local adresy
  • Dynamické přidělování adres
  • a další

Podrobnější informace a přihláška

Ohodnoťte jako ve škole:
Průměrná známka 2,96

Přehled názorů

tore
Yeti 28. 1. 2003 01:28
Nový
└ 
Re: tore
Nepto 28. 1. 2003 05:17
Nový
 
└ 
Re: tore
Yeti 28. 1. 2003 06:51
Nový
 
 
├ 
Re: tore
Yeti 28. 1. 2003 06:53
Nový
 
 
└ 
Re: tore
Nepto 1. 2. 2003 07:01
Nový
Jen drobnost
Jiri Svoboda 28. 1. 2003 09:57
Nový
Poradil by mi nekdo?
froid 28. 1. 2003 11:02
Nový
├ 
Re: Poradil by mi nekdo?
Michal Burda 28. 1. 2003 11:38
Nový
├ 
Re: Poradil by mi nekdo?
kokot 28. 1. 2003 11:41
Nový
└ 
Re: Poradil by mi nekdo?
Yeti 28. 1. 2003 13:10
Nový
 
└ 
pouzivam sed v bashi
froid 28. 1. 2003 14:33
Nový
 
 
├ 
Re: pouzivam sed v bashi
Yeti 28. 1. 2003 15:01
Nový
 
 
│
└ 
Re: pouzivam sed v bashi
moje 28. 1. 2003 17:15
Nový
 
 
│
 
└ 
Re: pouzivam sed v bashi
Yeti 28. 1. 2003 17:48
Nový
 
 
├ 
Re: pouzivam sed v bashi
jam 28. 1. 2003 16:09
Nový
 
 
└ 
Re: pouzivam sed v bashi
moje 28. 1. 2003 17:21
Nový
 
 
 
└ 
Re: perl
Tomik Janousek 28. 1. 2003 18:49
Nový
 
 
 
 
└ 
Re: perl
Jenda 3. 2. 2003 22:38
Nový
mimo jine
kokot 28. 1. 2003 11:38
Nový
├ 
dekuji za rady
froid 28. 1. 2003 13:08
Nový
└ 
Re: mimo jine
Jenda 3. 2. 2003 22:41
Nový
Deterministicky vs. nedeterministicky
Jirka Kosina 28. 1. 2003 11:53
Nový
└ 
Re: Deterministicky vs. nedeterministicky
smrt 28. 1. 2003 12:30
Nový
regex->automat
smrt 28. 1. 2003 12:14
Nový
mastering regular expressions (pdf)
mico 29. 1. 2003 08:12
Nový
└ 
Re: mastering regular expressions (pdf)
sfsd 20. 1. 2006 09:26
Nový
Bilý znak
Jarda 29. 1. 2003 12:25
Nový
└ 
Re: Bilý znak
lzap 6. 2. 2003 12:16
Nový
OpenOffice
Jan Hradek 29. 1. 2003 14:00
Nový
Preklad regularek do C
Jan Kotek 29. 1. 2003 14:02
Nový
└ 
Re: Preklad regularek do C
TheBurn 12. 2. 2005 13:41
Nový
 
└ 
Re: Preklad regularek do C
Martin 21. 2. 2010 09:39
Nový
Vynikajuci clanok
bloody 31. 1. 2003 08:42
Nový
bez titulku
anonymní uživatel 7. 2. 2003 12:21
Nový
aby nebylo "asp" na konci?
Bébul 20. 3. 2003 09:56
Nový
diky
koudis 3. 4. 2004 16:38
Nový
Absence znaku &
dense 1. 3. 2006 09:35
Nový
└ 
Re: Absence znaku &
fra.iesus 6. 5. 2007 14:13
Nový
oznaceni skupiny
padan 20. 3. 2011 12:32
Nový
Vyhledání hexdecimálu na začátku řetězce
Georgo 31. 5. 2011 13:36
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem