Edvard Rejthar na blogu zaměstnanců CZ.NIC představil svou aplikaci SlideRshow (GitHub). Funguje jako prohlížeč fotek, ale i jako jejich organizér a prezentátor. Neinstaluje se, běží přímo v prohlížeči. Bez serveru. Offline.
Kermit, tj. protokol pro přenos souborů, vznikl před 45 lety. Při této příležitosti byla po 15 letech od vydání poslední stabilní verze 9.0.302 vydána nová stabilní verze 11 implementace C-Kermit. S podporou IPv6.
První verze konverzního nástroje Pandoc byla vydána před 20 lety. Jeho autor John MacFarlane při tomto výročí rekapituluje jednotlivé etapy vývoje a přidávání nových funkcí – rozšíření nejen Markdownu a podporu mnoha dalších formátů.
Srpen přinesl nejen další spalující vedro, ale také Virtuální Bastlírnu s neméně žhavými novinkami. Využijte tedy předpovědi na deštivý čtvrteční večer a od 20:00 se připojte online k tomuto neformálnímu setkání kutilů, techniků a vědců, kde se strahovskými bastlíři proberete nejzajímavější věci, na které jste narazili za poslední měsíc. Pokud jde o novinky, řeč zcela jistě přijde na systém INDX pro tiskárny Průša, který na konci
… více »Firma T-Mobile blokovala „dezinformační web“ AC24 bez toho, aniž by k tomu měla závazný pokyn orgánů veřejné moci. Píše to ve svém rozsudku Městský soud v Praze, který po čtyřech letech uzavřel kauzu blokace zmíněného webu. Operátor musí uhradit škodu ve výši 35 tisíc korun. Advokát společnosti T-Mobile se snažil i u odvolacího senátu argumentovat tím, že firma jednala v dobré víře, když na stránky omezila přístup poté, co ji k tomu vyzvalo
… více »Padla obžaloba v bitcoinové kauze. Státní zástupkyně chce pro Blažka 6,5 roku vězení, pro Titze 8 let.
Z aktuálních globálních statistik společnosti Statcounter: na desktopu má Linux celosvětově podíl 7,53 % (USA 11,92 %, Česko 4,31 %, Slovensko 4,36 %) a Firefox celosvětově podíl 6,51 % (USA 10,86 %, Česko 11,07 %, Slovensko 13,61 %).
Na GitHubu byl publikován seznam 55 kritických bezpečnostních chyb v SQLite s přiřazenými CVE čísly. JFrog Security informuje, že se jedná jenom o AI slop, části kódu na které CVE odkazují, v daných verzích vůbec neexistují. Upozorňuje také, že čísla CVE jsou přiřazována bez ověřování.
Příspěvek na blogu Google Security popisuje, jak tým Chrome Security využívá umělou inteligenci k zásadnímu zrychlení a zlepšení procesu odhalování, třídění a opravování bezpečnostních chyb v prohlížeči Chrome. Díky AI byla nalezena kritická chyba, která byla v kódu přes 13 let. Ve verzích Chrome 149 a 150 bylo opraveno více chyb než v předchozích 23 verzích dohromady.
Firmy v EU musí počínaje dnešním dnem označovat obsah vytvořený umělou inteligencí. Znamená to povinnost informovat uživatele, že člověk komunikuje s chatbotem či jiným systémem AI. Rovněž obrázky, audia či videa, které jsou vytvořené nebo zmanipulované pomocí umělé inteligence a které mohou působit jako autentické, musejí být jasně označeny jako uměle vytvořené.
1. Stručný úvod
2. Operátor =~
3. Metoda sub (sub!)
4. Metoda gsub (gsub!)
5. Pamatování si vyhovujících řetězců
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 Satrapy – Regulá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?
=~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>
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>
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.
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>
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
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.).