abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 05:44 | Bezpečnostní upozornění

    Balíček s příkazem sudo byl vydán ve verzi 1.9.17p1. Řešeny jsou zranitelnosti CVE-2025-32462 (lokální eskalace práv prostřednictvím volby host) a CVE-2025-32463 (lokální eskalace práv prostřednictvím volby chroot).

    Ladislav Hagara | Komentářů: 0
    dnes 05:22 | IT novinky

    Do služeb Seznam.cz se lze nově přihlásit pomocí služby MojeID [𝕏].

    Ladislav Hagara | Komentářů: 0
    dnes 03:33 | Bezpečnostní upozornění

    Bezpečnostní výzkumníci zveřejnili informace o osmi zranitelnostech, které postihují více než 700 modelů tiskáren, skenerů a štítkovačů značky Brother. Bezpečnostní upozornění vydali také další výrobci jako Fujifilm, Ricoh, Konica Minolta a Toshiba. Nejzávažnější zranitelnost CVE-2024-51978 umožňuje útočníkovi vzdáleně a bez přihlášení získat administrátorská oprávnění prostřednictvím výchozího hesla, které lze odvodit ze

    … více »
    Ladislav Hagara | Komentářů: 0
    včera 16:00 | Komunita

    Společnost Oracle vlastní ochrannou známku JAVASCRIPT. Komunita kolem programovacího jazyka JavaScript zastoupena společností Deno Land vede právní bitvu za její osvobození, viz petice a otevřený dopis na javascript.tm. Do 7. srpna se k nim má vyjádřit Oracle (USPTO TTAB).

    Ladislav Hagara | Komentářů: 2
    včera 13:11 | IT novinky

    Byl představen samostatný rádiový modul Raspberry Pi Radio Module 2 s Wi-Fi a Bluetooth.

    Ladislav Hagara | Komentářů: 6
    včera 12:44 | Upozornění

    Certifikační autorita Let’s Encrypt ukončila k 4. červnu zasílání e-mailových oznámení o vypršení platnosti certifikátů. Pokud e-maily potřebujete, Let’s Encrypt doporučuje některou z monitorovacích služeb.

    Ladislav Hagara | Komentářů: 0
    včera 01:44 | Pozvánky

    Přemýšlíte, jak začít prázdniny? Už v úterý 1. července se bude konat Virtuální Bastlírna, tedy online setkání bastlířů, techniků, vědců i akademiků, kde se ve volné diskuzi probírají novinky ze světa techniky, ale i jiných zajímavých témat.

    Za poslední měsíc jsme byli svědky plamenů několika raket. Zatímco malá raketa od Hondy se úspěšně vznesla a opět přistála, raketa od SpaceX se rozhodla letět všemi směry najednou. Díkybohu méně … více »
    Uprdkávač | Komentářů: 0
    29.6. 23:44 | Komunita

    Linus Torvalds zmínil, že souborový systém Bcachefs zřejmě odstraní z mainline Linuxu v začleňovacím okně pro vydání 6.17. Kent Overstreet mu totiž posílá kód s novou funkcionalitou i pro začlenění do kandidátů na vydání, kdy očekává pouze opravy chyb. Kent Overstreet byl již dříve z vývoje vyloučen kvůli konfliktní komunikaci.

    Fluttershy, yay! | Komentářů: 11
    27.6. 11:55 | IT novinky

    Ministerstvo průmyslu a obchodu propaguje Microsoft. Ten ve spolupráci s Ministerstvem průmyslu a obchodu spouští AI National Skilling Plan v ČR. "Iniciativa Microsoftu přináší konkrétní a praktickou podporu právě tam, kde ji nejvíc potřebujeme – do škol, firem i veřejné správy.", říká ministr průmyslu a obchodu Lukáš Vlček.

    Ladislav Hagara | Komentářů: 33
    27.6. 10:55 | Zajímavý projekt

    Jste český ISP? Vyplněním krátkého dotazníku můžete pomoci nasměrovat vývoj nové generace routerů Turris Omnia [𝕏].

    Ladislav Hagara | Komentářů: 4
    Jaký je váš oblíbený skriptovací jazyk?
     (59%)
     (28%)
     (7%)
     (2%)
     (0%)
     (1%)
     (3%)
    Celkem 335 hlasů
     Komentářů: 16, poslední 8.6. 21:05
    Rozcestník

    Ruby pro začátečníky - 6 (regulární výrazy)

    9. 8. 2006 | Jaromír Hradílek | Programování | 9476×

    Dnes si stručně ukážeme, co to jsou regulární výrazy, a jak je v Ruby použít.

    Obsah

    1. Stručný úvod
    2. Operátor =~
    3. Metoda sub (sub!)
    4. Metoda gsub (gsub!)
    5. Pamatování si vyhovujících řetězců

    1. Stručný úvod

    Jste-li uživatelem Linuxu nebo jiného systému unixového typu a nebojíte se příkazové řádky, pravděpodobně jste se už s regulárními výrazy setkali. Využívá jich napřiklad streamový editor sed, vyhledávací program grep a spousta textových editorů (vim, kate) a dalších programů (less, awk). Regulární výraz je jakýsi vzor, podle nějž se vyhledává řetězec v textu, obvykle za účelem provedení nějaké operace, typicky náhrady za jiný řetězec nebo extrakce určitých údajů.

    Regulární výrazy jsou samy o sobě látkou dosti obsáhlou a jejich detailní výuka není účelem tohoto seriálu – od toho jsou zde povolanější, například vynikající seriál Pavla SatrapyRegulární výrazy. Pokud jste se s nimi tedy dosud nesetkali, doporučuji po přečtení tohoto článku prostudovat výše zmíněné materiály. Ačkoli jejich zvládnutí není pro další pokračování v jazyku Ruby nezbytné, jejich ignorací se připravíte o velmi silný nástroj, a to nejen v Ruby.

    Jak už jsem řekl v úvodu, regulární výraz je vlastně vzor pro vyhledávání v textu a v jazyce Ruby se uzavírá mezi dopředná lomítka /. Nejjednodušším vzorem je libovolný znak, tyto znaky pak lze zřetězit do slov:

    /a/     # Tomuto vzoru vyhovuje libovolný výskyt písmene a.
    /ahoj/  # Tomuto vzoru vyhovuje libovolný výskyt slova ahoj.
    /1984/  # Tomuto vzoru vyhovuje libovolný výskyt čísla 1984.

    Je třeba podotknout, že regulární výrazy jsou ve výchozím stavu case-sensitive, tedy rozlišující velikost písmen. Výrazu /ahoj/ tedy vyhovuje ahoj, zatímco Ahoj nebo AHOJ už ne.

    Toto dozajista není nijak zvlášť oslňující. Pravá kouzla však přichází až s výčtem speciálních vzorů, které Ruby rozeznává:

    zápis: význam:
    [] Výčet znaků, které se mohou na daném místě vyskytovat, včetně rozsahů.
    Např. [a-z] vyhovuje všem znakům malé (anglické) abecedy, [Aa] vyhovuje malému i velkému písmenu a.
    ^ Uvedena jako první znak výrazu zastupuje začátek řádku.
    Uvedena bezprostředně za otevírací hranatou závorkou výčtu plní funkci negace, např. [^a] vyhovuje jakémukoli znaku krom malého a.
    $ Uveden na konci regulárního výrazu zastupuje konec řádku.
    \w Libovolný alfanumerický znak. Ekvivalentní zápisu [a-zA-Z0-9]
    \W Cokoli jiného než alfanumerický znak. Ekvivalentní zápisu [^a-zA-Z0-9]
    \s Tzv. bílý znak, tedy mezera, tabulátor, nový řádek,… Ekvivalentní [ \t\n\r\f]
    \S Cokoli jiného než bílý znak. Ekvivalentní [^ \t\n\r\f]
    \d Libovolná jedna cifra. Ekvivalentní [0-9]
    \D Cokoli jiného než numerický znak. Ekvivalentní [^0-9]
    . Libovolný jeden znak.
    * Žádný nebo libovolný počet výskytů předchozího znaku.
    + Jeden nebo libovolný počet výskytů předchozího znaku.
    ? Žádný nebo jeden výskyt předchozího znaku.
    {m,n} Nejméně m, nejvýše n výskytů předchozího znaku.
    | Slouží jako logické nebo.
    Např.: /maly|velky/ vyhovuje řetězci maly, ale také velky
    () Slouží k seskupování znaků, např. /(ha)+/ vyhovuje ha, haha atd.
    Text vyhovující výrazu v závorkách je zároveň ukládán do paměti, viz dále.

    Jakkoli to zpočátku vypadá komplikovaně, když vám přejdou do krve, stanou se regulární výrazy vítaným pomocníkem, a to zdaleka nejen v Ruby. A abychom nezůstali jen u teorie, pojďme se společně podívat na několik ukázek použití.

    Řekněme, že chceme v konfiguračním souboru lokalizovat IP adresu. IPv4 se skládá ze čtyř čísel v rozsahu od 0 do 255, vzájemně oddělených tečkami (např. 192.168.1.3). Způsobů, jak napsat vyhovující vzor, je pochopitelně více, uveďme si jen pár z nich:

    /\d+\.\d+\.\d+\.\d+/                              # Nepřesné.
    /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/              # Lepší.
    /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/  # Extrém!

    První případ je jednoduchý a stručný, není však dostatečně přesný, vzoru totiž vyhoví i neplatná adresa (např. 192.1689.1.3), často však postačí. Druhý příklad je už přísnější, ačkoli stále připouští neplatné adresy, kdy cifra přesahuje 255 (např. 192.999.1.3), což se dá ovšem snadno ošetřit dále v programu. Třetí příklad je přepisem druhého aby bylo vidět, že to lze i složitěji.

    Povšimněte si, že před každou tečkou je zpětné lomítko. Samostatná tečka má totiž ve výrazu význam libovolného znaku. Předcházejícím zpětným lomítkem explicitně říkáme, že chceme skutečně tečku. Podobně bychom postupovali i v případě ostatních rezervovaných znaků, včetně zpětného lomítka:

    /\d+\s*\+\s*\d\s*=\s*\d+/   # Vyhovuje zápisu součtu dvou čísel, např.:
                                # 15 + 9 = 24
    /[a-zA-Z]:\\/               # Vyhovuje uživatelskému promptu Windows,
                                # např.: C:\
    /\*[A-Z][A-Z ]+\*/          # Vyhovuje textovým ICQ5 emotikonám, např.:
                                # *THUMBS UP* nebo *JOKINGLY*
    

    Říkal jsem, že Ruby implicitně rozlišuje velikost písmen. Co když ale nevíme, jakým způsobem bude daný text zapsán (typicky přípony souborů stažených z internetu)? Představme si, že máme soubor, kde je na každém řádku uveden název souboru a my chceme vyhledat jen ty ve formátu Ogg Vorbis. Jednou z možností by bylo uvést všechny možnosti:

    /^[\w ]+.[Oo][Gg][Gg]/

    Toto je sice v případě třípísmenné přípony ještě únosné, kdybychom ale hledali delší text, asi bychom se uzávorkovali. Ruby naštěstí umožňuje rozlišování velikosti písmen explicitně vypnout a to uvedením volby i (case insensitive), již zapisujeme za uzavírací lomítko:

    /^[\w ]+.ogg/i

    Přehlednější, že ano?

    2. Operátor =~

    Po zvládnutí základů je na čase ukázat si, jak jich využít přímo v jazyce. Velmi často se používá operátor =~ který zjistí, zda se v řetězci vyskytuje nějaká část vyhovující vzoru. Pokud ano, vrátí číselný index prvního znaku nalezeného řetězce, v opačném případě vrátí hodnotu nil. Ukažme si to třeba na našem příkladu s ICQ emotikony:

    irb(main):001:0> "tak to uz je spatny*TIRED*:-P" =~ /\*[A-Z][A-Z ]+\*/
    => 19
    irb(main):002:0> ":-* ;-) :-*" =~ /\*[A-Z][A-Z ]+\*/
    => nil
    irb(main):003:0>
    

    Protože jako false je v Ruby krom false samotného vyhodnoceno už jen nil a cokoli jiného se automaticky vyhodnocuje jako true, lze operátor =~ bez obav použít k větvení programu:

    irb(main):003:0> my_ip = "192.168.1.3"
    => "192.168.1.3"
    irb(main):004:0> if my_ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
    irb(main):005:1>   puts "Ok."
    irb(main):006:1> else
    irb(main):007:1*   print "Zadejte prosim svou IP: "
    irb(main):008:1>   my_ip = gets.chomp
    irb(main):009:1> end
    Ok.
    => nil
    irb(main):010:0>

    Tento příklad má jednu vadu a to tu, že dále nezkoumá uživatelský vstup. To řeší třeba následující ukázka s cyklem:

    irb(main):010:0> my_ip = ""
    => ""
    irb(main):011:0> until my_ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
    irb(main):012:1>   print "Zadejte prosim svou IP: "
    irb(main):013:1>   my_ip = gets.chomp
    irb(main):014:1> end
    Zadejte prosim svou IP: Nepovim. :-P
    Zadejte prosim svou IP: localhost
    Zadejte prosim svou IP: 192.168.1.3    
    => nil
    irb(main):015:0> puts my_ip
    192.168.1.3
    => nil
    irb(main):016:0>

    A když už jsme u těch řídících struktur, byla by škoda si neukázat, že lze regulární výrazy bez obav použít i v konstrukci case:

    irb(main):016:0> vypocet = "19 - 7 = 12"
    => "19 - 7 = 12"
    irb(main):017:0> case vypocet
    irb(main):018:1>   when /\d+\s*\+\s*\d\s*=\s*\d+/
    irb(main):019:1>     puts "Soucet."
    irb(main):020:1>   when /\d+\s*-\s*\d\s*=\s*\d+/
    irb(main):021:1>     puts "Rozdil."
    irb(main):022:1>   when /\d+\s*\*\s*\d\s*=\s*\d+/
    irb(main):023:1>     puts "Soucin."
    irb(main):024:1>   when /\d+\s*[:\/]\s*\d\s*=\s*\d+/
    irb(main):025:1>     puts "Podil."
    irb(main):026:1>   else
    irb(main):027:1*     puts "Juj, tak ted jsi me dostal. :-o"
    irb(main):028:1> end
    Rozdil.
    => nil
    irb(main):029:0>

    3. Metoda sub (sub!)

    Dalším běžným úkonem bývá náhrada textu za jiný. Pro datový typ String je proto definována metoda sub, jejíž zápis je následující:

    řetězec.sub(vzor, náhrada)

    Představte si, že chcete přenést skript pro nastavení pravidel iptables ze svého laptopu s Debianem na PC se Slackware. Jenže ejhle, všude voláte iptables s absolutní cestou a ta je ve Slackware jiná. Necháme-li stranou, že by byl na takový úkon patrně vhodnější sed (nebo mít ve skriptu cestu uloženou v proměnné), mohla by část vykonávající náhradu vypadat třeba takto:

    irb(main):029:0> radek = "/sbin/iptables -A INPUT -i $IN -p tcp --syn -j dos"
    => "/sbin/iptables -A INPUT -i $IN -p tcp --syn -j dos"
    irb(main):030:0> radek.sub(/\/sbin\/iptables/, "/usr/sbin/iptables")
    => "/usr/sbin/iptables -A INPUT -i $IN -p tcp --syn -j dos"
    irb(main):031:0>
    

    Teoreticky tedy procházíme skript, kdy každý řádek načítáme do proměnné radek a tu pak zpracováváme. Metoda sub nám nicméně obsah proměnné nemění, pozměněný řetězec předává jako návratovou hodnotu. Kdybychom chtěli záměnu aplikovat přímo na proměnnou, použijeme verzi s vykřičníkem:

    irb(main):031:0> radek.sub!(/\/sbin\/iptables/, "/usr/sbin/iptables")
    => "/usr/sbin/iptables -A INPUT -i $IN -p tcp --syn -j dos"
    irb(main):032:0> puts radek
    /usr/sbin/iptables -A INPUT -i $IN -p tcp --syn -j dos
    => nil
    irb(main):033:0>
    

    4. Metoda gsub (gsub!)

    Metoda sub má jen jednu „nevýhodu“ – uplatňuje se pouze na první výskyt vyhovujícího řetězce:

    irb(main):033:0> ":p :p :p".sub(/:p/, ":-P")
    => ":-P :p :p"
    irb(main):034:0>

    Jsou situace, kdy nám to nevadí nebo toho s výhodou využijeme, jindy se nám to ale nemusí vůbec hodit. Naštěstí existuje metoda gsub, která provede náhradu všech řetězců vyhovujících vzoru:

    irb(main):034:0> ":p :p :p".gsub(/:p/, ":-P")
    => ":-P :-P :-P"
    irb(main):035:0>

    Stejně jako v případě sub má i gsub variantu s vykřičníkem.

    5. Pamatování si vyhovujících řetězců

    V tabulce jsem se u závorek zmiňoval, že řetězec vyhovující vzoru mezi nimi je ukládán do paměti. Existují dva způsoby, jak se k nim dostat, a prvním z nich je prostřednictvím proměnné $n, kde n je číslo udávající pořadí závorek:

    irb(main):035:0> udaj = "NAME=Feyd-Rautha Harkonnen"
    => "NAME=Feyd-Rautha Harkonnen"
    irb(main):036:0> if udaj =~ /^NAME=([^ ]+) (.*)$/
    irb(main):037:1>   puts "Krestni jmeno: " + $1
    irb(main):038:1>   puts "Prijmeni:      " + $2
    irb(main):039:1> end
    Krestni jmeno: Feyd-Rautha
    Prijmeni:      Harkonnen
    => nil
    irb(main):040:0>

    Druhý způsob – zápis ve tvaru \n – se používá přímo v regulárních výrazech. Dejme tomu, že máme v textovém souboru seznam jmen ve tvaru jméno příjmení, ovšem kvůli snazšímu vyhledávání bychom chtěli příjmení na prvním místě. Toho dosáhneme třeba takto:

    irb(main):040:0> jmeno = "John Ronald Reuel Tolkien"
    => "John Ronald Reuel Tolkien"
    irb(main):041:0> jmeno.sub!(/^(.*) ([^ ]+)$/, '\2 \1')
    => "Tolkien John Ronald Reuel"
    irb(main):042:0>
           

    Hodnocení: 75 %

            špatnédobré        

    Nástroje: Tisk bez diskuse

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    Komentáře

    Vložit další komentář

    Marek Bernát avatar 9.8.2006 07:06 Marek Bernát | skóre: 17 | blog: Arcadia
    Rozbalit Rozbalit vše Re: Ruby pro začátečníky - 6 (regulární výrazy)
    Chápem, že regulárne výrazy sú dôležité, ale neviem prečo treba ich základy duplikovať do každého tutoriálu o programovacích jazykoch. Nebolo by lepšie dať odkaz na (lepší) tutoriál pre regulárne výrazy a zamerať sa len na špecifické operácie konkrétneho jazyka?

    Poprosím len koštruktívne komentáre, toto má byť návrh na vylepšenie, ak to nie je zrejmé.
    physics.stackexchange.com -- Q&A stránky o fyzike v štýle StackOverflow.
    9.8.2006 09:52 Robert Krátký | skóre: 94 | blog: Robertův bloček
    Rozbalit Rozbalit vše Re: Ruby pro začátečníky - 6 (regulární výrazy)
    Nebolo by lepšie dať odkaz na (lepší) tutoriál pre regulárne výrazy a zamerať sa len na špecifické operácie konkrétneho jazyka?
    Mám za to, že to takhle článek udělal. Lehký úvod do problematiky, seznámení, odkaz na tutoriál a popis toho, jak výrazy používat v Ruby (zkratky, operátory atd.).
    Marek Bernát avatar 9.8.2006 20:15 Marek Bernát | skóre: 17 | blog: Arcadia
    Rozbalit Rozbalit vše Re: Ruby pro začátečníky - 6 (regulární výrazy)
    Ospravedlňujem sa autorovi, tú linku som prehliadol :-(
    physics.stackexchange.com -- Q&A stránky o fyzike v štýle StackOverflow.
    17.8.2006 13:28 Miroslav Pecka
    Rozbalit Rozbalit vše Re: Ruby pro začátečníky - 6 (regulární výrazy)
    Téměř vše o regulárních výrazech (články, hotová řešení, testery, diskuzní fórum) najdete na webu Regulární výrazy.

    Založit nové vláknoNahoru

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.