ARCHIV |
|||||
Software (10844)
Distribuce (131)
Skripty (697)
Menu
Diskuze
Informace
|
Perl (24) - Regulární výrazy - příkladyNáš miniseriál se pomalu chýlí ke konci. Předposlední díl bude ryze praktický. Již znáte řadu konstrukcí, které se v regulárních výrazech používají, ale jedna důležitá věc stále chybí. Dosud zde byly regulární výrazy podány výhradně teoreticky. Dnes se to změní, protože celý díl je věnován čistě příkladům. Testování vstupuTo, že je třeba každý vstup z neověřeného zdroje testovat, je jasné. A právě regulární výrazy nabízejí spolehlivé a pohodlné řešení. Mechanizmus takového testování si ukážeme. Budeme chtít po uživateli zadat trojciferné číslo a vzápětí zkontrolujeme, zda ho opravdu zadal. Na takové drobnosti se regulární výrazy využívají velmi často.
print "Zadej trojciferné číslo: "; Validace emailové adresyVyjádření emailové adresa je další regulární výraz, který patří k těm nejčastějším. Dokonalý zápis je velice složitý. Jeho vytvoření je popsáno v knize Mastering Regular Expressions. My se spokojíme s poměrně jednoduchým zápisem. Před zavináčem povolíme alfanumerické znaky a dále tečku a pomlčku. Část za zavináčem se skládá ze 2 částí. Doménu lze vyjádřit stejně jako jméno před zavináčem a přípona se skládá ze 2-4 písmen. Uvádím pouze samotný regulární výraz:
/^[\w\.-]+@[\w\.-]+\.[a-z]{2,4}$/i
Hledání odkazů v HTML souboruMáme HTML soubor. Z něj chceme získat vše, co je mezi <a href=" a "> a mezi <a...> a </a>. Tedy odkaz a jeho popis. Získaná data vytiskneme. Budeme postupně načítat řádky souboru (nebudeme brát ohled na odkazy obsahující znak nového řádku). V každém řádku se pokusíme najít HTML odkaz, z něj zapamatujeme adresu a popis a vytiskneme. Protože mohou existovat řádky bez odkazu, je nutné tisknout pouze v případě, že porovnání vzoru bylo úspěšné. Toho dosáhneme podmíněnním příkazu print. Dále víme, že HTML není case sensitive. Proto přidáme přepínač i.
open SOUBOR, "index.html" or die "Nelze otevřít soubor. $!"; Vyvstává nám tu několik problémů. Co když je na 1 řádku více odkazů? Na každý řádek se totiž aplikuje regulární výraz pouze jednou, není proto šance najít více než 1 odkaz. Problém by vyřešil další cyklus. Není ale potřeba nic zásadně upravovat. Pouze if zaměníme za while. Dalším problémem jakým způsobem vyhoví řetězce jako <a href="xxx'...> Jako odkaz se vyseparuje pouze xxx. Jinými slovy musíme zajistit, aby byly oba uvozující znaky stejné. To je úloha jako šitá pro pamatování. Uzavřeme tedy úvodní uvozovací znak do závorek (['"]) a místo dalšího ['"] pro uzavření jen \1. Podobně upravíme část ([^"']*), kde nahradíme znaky "' za \1. Po provedení úprav získáváme již funkční program:
open SOUBOR, "index.html" or die "Nelze otevřít soubor. $!"; Zvýraznění skalárních proměnnýchVytvoříme nástroj, který přijímá jako parametr soubor, ve kterém zvýrazní všechny skalární proměnné. Bude-li se například vyskytovat v textu řetězec '$promenna', bude nahrazen za '<font color="#800000">$promenna</font>'. Každou iterací cyklu načteme řádek zdrojového kódu Perlu, v něm zvýrazníme výskyty proměnných a vytiskneme výsledek. Jediný problém tak spočívá ve vytvoření vzoru, kterému vyhoví identifikátor skalární proměnné. Vzor bude začínat dolarem, následuje libovolné písmeno nebo podtržítko (nebereme ohled na speciální proměnné) a nakonec libovolný počet znaků slova. Celý vzor uzavřeme do kulatých závorek, získáme tak proměnnou $1, kterou použijeme jako část náhrady.
while (<>){ Získání adresáře a jména souboru z umístěníŘetězec, který je cestou k souboru, rozdělíme na 2 části. Na adresář, ve kterém je daný soubor a jeho relativní jméno. Víme, že oddělovacím znakem je poslední lomítko. Využijeme tak hladovosti kvantifikátorů.
$umisteni = "/boot/grub/menu.lst"; Výpočet výrazů v textuNa vstupu přijme program textový řetězec, ve kterém se občas může vyskytnout podřetězec <<výraz>>. Výraz vyhodnotíme a získanou hodnotu za něj nahradíme. Budeme tedy postupně načítat řádky textu a v něm takové výrazy hledat. Na 1 řádku se může vyskytnout více výrazů, proto použijeme přepínač g. Další přepínač, který aplikujeme, je e. Umožňuje nám přímo v regulárním výrazu nahrazovat za výsledek nějakého výrazu. A použijeme ho hned 2krát, protože ještě potřebujeme vyhodnotit řetězec, jako by byl částí zdrojového kódu.
while (<>){ Spíše jen pro ukázku zde uvádím zápis stejného programu, který používá pouze jeden přepínač e. Funkce eval může ten druhý zastoupit.
while (<>){ Pošleme programu na vstup řetězec
Týden má <<7>> dní, <<7*24>> hodin, <<7*24*60>> minut nebo <<7*24*60*60>> sekund. a získáme
Týden má 7 dní, 168 hodin, 10080 minut nebo 604800 sekund.
Upozorňuji, že toto je jen ilustrační příklad na regulární výrazy. Mimo jiné je totiž také velkou bezpečnostní dírou. Umožňuje spuštění příkazů. Například po zadání řetězce "...<<system("rm soubor")>>..." bude proveden systémový příkaz rm soubor. Speciální techniky, kterými se lze chránit, probereme někdy v budoucnu. Zdvojení všech znaků slova v řetězciProblém vyřešíme tak, že vyhledáme všechny (přepínač g) výskyty znaků slova a ty jednoduše zdvojíme. Nejlepší řešení vede přes pamatování, ale abychom vyzkoušeli také něco dalšího, použijeme proměnnou $&.
$_ = "LINUX & PERL"; Validace HTML taguHTML tagem může být <html>, <a href="http://www.linuxsoft.cz">, </b>, <img src="logo.png"/> nebo i <center >. Možností je celá řada. Pokusíme se je v co největší míře obsáhnout v našem řešení. Tag bude vždy začínat znakem < a končit znakem >. Za úvodním < následuje případné lomítko a dále samotné jméno tagu. To je složeno z nenulového počtu znaků slova. Potom je možných ještě několik bílých znaků, dále opět nepovinné lomítko a nakonec znak >. To je struktura tagu, který nemá žádné parametry. Argumenty se píší za jméno tagu. Může jich být libovolné množství. Každý z parametrů začíná bílým znakem. Tu následuje nenulový počet znaků slova. Nyní jsou v našem výrazu implementovány i přepínače. Ale stále chybí pravé parametry. Za přepínačem může nepovinně být rovnítko (případně obalené bílými znaky) a nějaká hodnota - v uvozovkách, apostrofech, nebo jako holé slovo. U HTML tagů nezáleží na velikosti písmen. O to se ale starat nemusíme, protože jsme nikde konkrétní velikost neuváděli. Když všechny tyto poznatky aplikujeme na regulární výraz, vznikne nám toto:
/ Ale nemůže to stále být konečné řešení, protože vyhoví i řetězec </x/>, který tagem rozhodně není. Lomítko tedy může být maximalně jedno - buď na začátku nebo na konci. Toho docílíme rozvětvením.
/ Generování příkazů INSERT z dat textového souboruNakonec si uvedeme (po testování vstupu) asi nejpraktičtější příklad. Řekněme si, že máme data v nějakém textovém souboru a chceme je dostat do databáze. Ve zdrojovém souboru je máme k dispozici ve formátu sloupec\tsloupec\tsloupec... (sloupce oddělené tabulátorem), tedy například: 20050101 50000 20050102 84000 20050103 0 20050102 -20000 20050104 47000 Právě pro případ dvou sloupců si napíšeme skript, který data převede na INSERT příkazy: INSERT INTO finance (datum, zisk) VALUES ("20050101", "50000"); INSERT INTO finance (datum, zisk) VALUES ("20050102", "84000"); INSERT INTO finance (datum, zisk) VALUES ("20050103", "0"); INSERT INTO finance (datum, zisk) VALUES ("20050104", "-20000"); INSERT INTO finance (datum, zisk) VALUES ("20050105", "47000"); Náš příklad je velmi konkrétní. Mělo by to usnadnit pochopení. Postupně načteme každý řádek, rozdělíme na jednotlivé sloupce a vygenerujeme INSERT příkaz.
open DATA, "data" or die "Nelze cist zdroj dat\n"; Poznámka - samozřejmě by šlo rozdělení řešit jednodušeji přes split:
($datum, $zisk) = split "\t", $_; Zkusíme si ještě podobnou věc a to generování INSERT příkazů z dokumentů tabulkových editorů. Přesně toto jsem kdysi potřeboval a někde jsem našel velice hezké řešení. Prvním krokem je uložit dokument v nějakém textovém formátu - například CSV. CSV soubor může vypadat třeba takto:
0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0 Středníky jsou oddělovače sloupců a konce řádků oddělovače řádků. V každé buňce máme hodnotu 0 nebo 1. Tuto dvojrozměrnou strukturu budeme ukládat do jednoho rozměru. Pro každou buňku budeme tedy chtít v databázi uložit její souřadnice.
my $radek; Poznámka - rozdělení by opět šlo řešit jednodušeji použitím funkce split:
@radek = split(";", $radek); Dnes jsem se pokusil ukázat široké využití regulárních výrazů. Doufám, že jsem vám dodal alespoň trochu inspirace. Příští díl bude ze série o regulárních výrazech poslední. Podíváme se na měření rychlosti a debugging.
Související články
Předchozí Celou kategorii (seriál) Další
Perl (1) - Dávka teorie na úvod
Perl (2) - Úvod do syntaxe Perl (3) - Proměnné Perl (4) - Čísla a řetězce Perl (5) - Podmínky Perl (6) - Pravdivostní výrazy Perl (7) - Vstup poprvé Perl (8) - Některé základní vestavěné funkce Perl (9) - Cykly Perl (10) - Další řídící struktury Perl (11) - Pole - úvod Perl (12) - Pole - základní operace Perl (13) - Hashe Perl (14) - Další nástroje pro seznamy Perl (15) - Výchozí proměnná, heredoc, symbolické odkazy Perl (16) - Regulární výrazy - začínáme Perl (17) - Regulární výrazy - kotvy Perl (18) - Regulární výrazy - množiny znaků Perl (19) - Regulární výrazy - opakování a kvantifikátory Perl (20) - Regulární výrazy - magické závorky Perl (21) - Regulární výrazy - nahrazování Perl (22) - Regulární výrazy - přepínače Perl (23) - Regulární výrazy - rozšířené vzory Perl (25) - Regulární výrazy - závěr Perl (26) - Podprogramy Perl (27) - Prototypy Perl (28) - Rozsahy platnosti proměnných Perl (29) - Úvod k práci se soubory Perl (30) - Práce se soubory Perl (31) - Testování souborů Perl (32) - Jiné typy souborů Perl (33) - Formátování výstupu - printf Perl (34) - Formátování výstupu - formáty Perl (35) - Vestavěný debugger Perl (36) - Grafické debuggery Perl (37) - Začínáme s moduly Perl (38) - Rozhraní modulu Perl (39) - Pragma Perl (40) - Dodatky k modulům Perl (41) - CPAN Perl (42) - Argumenty příkazového řádku Perl (43) - Přepínače Perl (44) - Dlouhé přepínače Perl (45) - Odkazy Perl (46) - Užití odkazů a anonymní data Perl (47) - Složitější datové struktury Perl (48) - Libovolně složité datové struktury Perl (49) - Tabulky symbolů a typegloby Perl (50) - Uzávěry a iterátory Perl (51) - Signály Perl (52) - Externí příkazy Perl (53) - Režim nakažení Perl (54) - Fork Perl (55) - Eval Perl (56) - Volby příkazu perl Perl (57) - Jednořádkové skripty Perl (58) - OOP - úvod Perl (59) - OOP - typické použití Perl (60) - OOP - dědičnost Perl (61) - OOP - přínos a užití dědičnosti Perl (62) - OOP - přetěžování Perl (63) - OOP - závěr Perl (64) - Projekt - čtečka sportovních výsledků Perl (65) - Projekt - získání dat Perl (66) - Projekt - výběr zápasů a podrobnosti Perl (67) - Projekt - dokončujeme modul Perl (68) - Projekt - zobrazení zápasů Perl (69) - Projekt - online přenos Perl (70) - Plain Old Documentation Perl (71) - Navazování proměnných Perl (72) - Navazování složitějších datových typů Perl (73) - DBM Perl (74) - Sockety Perl (75) - Obsluha více klientů Perl (76) - Síťová hra v kostky Perl (77) - Služby internetu Perl (78) - Databáze - úvod Perl (79) - Databáze - manipulace s daty Perl (80) - Databáze - závěrečné poznámky Perl (81) - CGI - příprava webového serveru Perl (82) - CGI - první skripty Perl (83) - CGI - získávání dat od uživatele Perl (84) - CGI - usnadnění tvorby skriptů pomocí modulu CGI Perl (85) - CGI - generování dokumentu modulem CGI Perl (86) - CGI - cookies Perl (87) - CGI - příklad aplikace Perl (88) - CGI - závěr Perl (89) - Mason - snadné psaní webů Perl (90) - Mason - speciální bloky Perl (91) - Mason - handlery Perl (92) - Mason - závěr Perl (93) - Catalyst - MVC framework pro Perl Perl (94) - Catalyst - základy pro psaní aplikace Perl (95) - Catalyst - šablony Perl (96) - Catalyst - spolupráce s databází Perl (97) - Curses - tvorba textových uživatelských rozhraní Perl (98) - Curses - pozicování a okna Perl (99) - Curses - měření rychlosti psaní Perl (100) - Curses - použití hotových widgetů Perl (101) - Curses - jednoduchý textový editor Perl (102) - Rozšiřování Perlu pomocí XS Perl (103) - Rozšiřování Perlu pomocí SWIG Perl (104) - Testování rychlosti Perl (105) - Testování programových jednotek Perl (106) - Debugování pomocí komentářů Perl (107) - Moose - moderní objektový systém Perl (108) - Moose - základní vlastnosti Perl (109) - Moose - role Perl (110) - Moose - meta API Perl (111) - Pokročilá práce se seznamy Perl (112) - Práce s PDF Perl (113) - Práce s archivy Perl (114) - Tk - úvod Perl (115) - Tk - umísťování widgetů Perl (116) - Tk - základní widgety Perl (117) - Tk - některé pokročilejší widgety Perl (118) - Tk - čas a události Perl (119) - Tk - CD man Perl (120) - Wx - základní práce s widgety Perl (121) - Wx - události Perl (122) - Gtk2 - úvod Perl (123) - Gtk2 - základní práce s obrázky Perl (124) - Gtk2 - události a čas Perl (125) - Gtk2 - vlastní widgety Perl (126) - Gtk2 - textové okno a práce s pozicemi Perl (127) - Gtk2 - hierarchické seznamy Perl (128) - Gtk2 - dialogy Perl (129) - Gtk2 - skládání widgetů Perl (130) - Gtk2 - menu a toolbary Perl (131) - Gtk2 - transparentní okna, tray ikona, výběr souborů Perl (132) - Gtk2 - drag&drop, druid Perl (133) - Gtk2 - úpravy vzhledu aplikací pomocí rc Perl (134) - Gtk2 - Glade Interface Designer Perl (135) - XML - čtení a zápis Perl (136) - XML - DOM a SAX přístupy Perl (137) - Vlákna Perl (138) - Memoizace - cachování podprogramů Perl (139) - Profilling - efektivní odhalování pomalých míst v programu Perl (140) - Profilling - píšeme si vlastní profiler / debugger Perl (141) - Formátování kódu, deparsování, perltidy Perl (142) - Způsoby konfigurování Perl (143) - Struktura datových typů, správa paměti Perl (144) - POE - událostmi řízené programování Perl (145) - POE - aplikace typu klient-server Perl (146) - Perl 6 - jazyk budoucnosti Perl (147) - Perl 6 - regulární výrazy, nové operátory Perl (148) - Perl Culture Perl (149) - Závěr Pozvánka na Český Perl Workshop Perl 5.22.0 a vše okolo Perl 5.24.0 a vše okolo Předchozí Celou kategorii (seriál) Další
|
Vyhledávání software
Vyhledávání článků
28.11.2018 23:56 /František Kučera 12.11.2018 21:28 /Redakce Linuxsoft.cz 6.11.2018 2:04 /František Kučera 4.10.2018 21:30 /Ondřej Čečák 18.9.2018 23:30 /František Kučera 9.9.2018 14:15 /Redakce Linuxsoft.cz 12.8.2018 16:58 /František Kučera 16.7.2018 1:05 /František Kučera
Poslední diskuze
31.7.2023 14:13 /
Linda Graham 30.11.2022 9:32 /
Kyle McDermott 13.12.2018 10:57 /
Jan Mareš 2.12.2018 23:56 /
František Kučera 5.10.2018 17:12 /
Jakub Kuljovsky | |||
ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2024) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze |