Regulární korektura Intervalu.cz
Regulární výrazy jsou vynálezem amerického
matematika Stephena
Kleene a troufám si tvrdit, že jsou starší než většina čtenářů La
Trine. Pro nezasvěcené působí jako tajemné formule s magickou silou.
Zdrojů, ze kterých se dají vědomosti o výrazech získat, je dost. Od
vyčerpávající nápovědy
v PHP, přes články až po knihy.
Člověk omámený kouzlem regulárních výrazů často propadne jejich
nadužívání. Proto je škoda, že neexistují i tituly jako „Deset
případů, kde se regexp absolutně nehodí“ nebo „Zpověď
programátora: Už týden jsem nepoužil regulární výraz“
Nebudu zde vysvětlovat principy regulárních výrazů – všechny zájemce bych rád odkázal na seriál Miroslava Pecky, který právě vychází na Intervalu. Protože jsme v něm narazil na určitou nesrovnalost, připojuji tuto svou korekturu.
Kde se vloudila chyba?
V části věnované subvýrazům a zpětným
referencím autor uvádí, že zpětné reference se zapisují ve tvaru
\\n, kde n je číslo subvýrazu. K tomu mám vážnou
námitku: zapisují se ve tvaru \n.
Svá slova potvrzuji tímto příkladem. Jasně
demonstruje, že při užití \2 \1 vše funguje dle očekávání,
zatímco \\2 \\1 ke zdárnému cíli nevede. Tedy rozdíl v jednom
lomítku je skutečně zásadní.
Poznámka: V regulárních výrazech nesmírně záleží na každém znaku, včetně mezer, a tudíž není možné tolerovat jakoukoliv nejasnost. Hledání chyb ve výrazech je mravenčí práce a může vést až k nervovým kolapsům včetně nepříjemného regurgitačního uvolnění organismu.
Něco tu nehraje
Co je zajímavé, příklady uvedené v článku Miroslava Pecky skutečně fungují, i s oním dvojitým lomítkem. Jak je to možné? Je to díky určité shodě okolností.
Každý programátor PHP by měl perfektně ovládat zápis řetězců. PHP k tomuto účelu nabízí hned tři způsoby, nejčastěji se používají tyto dva: uvození řetězce do jednoduchých a dvojitých uvozovek. Důležité je vědět, že takto zapsaný řetězec ještě PHP určitým způsobem transformuje do finální podoby.
V těchto transformacích hrají důležitou roli právě zpětná lomítka.
Pohledem na příslušné místo v dokumentaci
PHP zjistíte, že zápis "\50" podléhá transformaci a PHP
jej nahradí za znak s kódem 50 v osmičkové soustavě, což je mimochodem
levá závorka. Naopak při použití jednoduchých uvozovek k transformaci
nedojde:
echo "\50"; // vypíše (
echo "\\50"; // vypíše \50
echo '\50'; // vypíše \50
Z příkladu je vidět, že nechtěné transformaci se lze vyhnout zdvojením zpětného lomítka nebo (lépe) nahrazením dvojitých uvozovek za jednoduché.
A tím se dostáváme zpět ke kritizovaným zpětným referencím. Protože autor používá ve všech příkladech řetězce s dvojitými uvozovkami, musí zpětná lomítka zdvojovat. Tedy zdvojení si vynucuje vlastnost PHP, která s regulárními výrazy absolutně nesouvisí. Kdyby použil uvozovky jednoduché, zdvojovat lomítko není třeba (avšak nevadí to). Ve všech dalších případech (syntax heredoc, načítání z databáze nebo souborů, mnou uvedený příklad) už vadit bude a příklady přestanou fungovat.
Závěr: Doporučuji regulární výrazy zapisovat opatrně a nejlépe s použitím jednoduchých uvozovek.
Komentáře » přidat
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře ani hlasovat
dalsi duvod proc pouzivat jednoduche uvozovky :))
Já bych spíš napsal, že kdyby použil uvozovky jednoduché, tak by nevadilo, že lomítko není zdvojené.
Je to spíše filozofický problém, ale \ slouží k escapování i uvnitř apostrofů. Kromě samotného \ totiž escapuje i apostrof. Když za lomítkem nenásleduje escapovaný znak, tak se to jako záchrana přeloží na \ + původní znak.
Psát
'\\1'je tedy podle mě správnější, protože skutečně chci vypsat zpětné lomítko a ne něco escapovat.Napsat, že zpětné reference se uvozují \\ je samozřejmě špatně, ale možná to pan Pecka napsal proto, aby začátečníkům nezamotal hlavu.
Sorry za offtopic, ale jaky je treti zpusob zapisu retezce v PHP? Nejak me nic jinyho nez uvozovky dvojity/jednoduchy nenapada.
[3] spud: Je s odkazem uveden na konci článku, hledej HEREDOC.
Chudák ten, kdo si to vezme k srdci a bude chtít zkontrolovat např. Windows cestu a použije
'~c:\\windows\\system~i'(vědom si toho, že \w a \s jsou v regulárním výrazu speciální znaky). Co se stane? Dvojitá lomítka požere už PHP a na regulární výraz zbyde \w a \s, což jsou zkratky za znak pro slovo a pro bílý znak.[5] Jakub Vrána: je třeba zapsat
'~c:\\\\windows\\\\system~i', jinou cestu neznám. Ale nerozumím té narážce s chudákem a jeho srdcem.[6] David Grudl: To „to“ v [5] Jakub Vrána: odkazuje na „Kdyby použil uvozovky jednoduché, zdvojovat lomítko není třeba“, tedy citovaný text. Možná jsi citovaný text přehlédl.
Jakube, vím že v PHP jsi machr, nebude lepší celý problém vysvětlit začátečníkům, než se tu štengrovat mezi sebou?
Ty napadáš větu, že v zdvojovat lomítko není třeba, která však souvisí se zápisem řetězce
'\50'. A tady skutečně není třeba nic zdvojovat.Bych to celé vyřešil tak, jak doporučují v manuálu u preg_replace: