Regulární výrazy (5.) – Unicode

V pátém dílu seriálu o regulárních výrazech se podíváme na možnosti práce s kódováním Unicode, které se velmi hodí uživatelům exotických abeced (například české). Za běžných okolností je totiž knihovna PCRE nastavena pro práci s běžným osmibitovým kódováním znaků (co znak, to bajt), a ještě speciálně pro práci s anglickou abecedou. Abecedy ostatní standardním PCRE podporovány nejsou a buď nejsou použitelné vůbec (japonština a další abecedy, které potřebují více než jeden bajt na reprezentaci jednoho znaku) nebo jen s omezeními (např. čeština – v zásadě funguje, ale neexistuje žádná podpora pro skutečnost, že „č“ je „písmeno“ a ne „speciální symbol“). S podporou Unicode lze ale docela dobře pracovat i s neanglickými abecedami.

Zapnutí Unicode

PCRE byla původně navržena jen pro anglickou abecedu. Z důvodů zpětné kompatibility i nadále ve výchozím stavu pracuje jen s touto abecedou a tváří se, že o Unicode nic neví. Pokud tedy chcete s Unicode pracovat, musíte to knihovně dát explicitně vědět. To znamená:

  1. Musíte použít PCRE ve verzi nejméně 5.0 (září 2004) a raději novější. Starší verze Unicode neznají vůbec.

  2. Musíte použít PCRE zkompilované pro podporu Unicode. To, že máte dostatečně novou verzi knihovny, je pouze podmínka nutná, ale nikoliv postačující – každou verzi PCRE jde zkompilovat tak, aby Unicode nepodporovala. Například můj YouTube Downloader používá pro Delphi 2007 a starší PCRE zkompilovanou bez podporu Unicode, protože ji starší Delphi stejně neumožňují využít (respektive, Delphi samy by to dokázaly, ale to, jak je YTD napsaný, to činí bezpředmětným) a aspoň tak ušetřím pár desítek kilobajtů na distribučním archívu.

    V drtivé většině případů narazíte na PCRE s podporou Unicode zapnutou, vypnutá bývá jen ve vysloveně speciálních případech.

  3. Při každém použití nějakého regulárního výrazu musíte PCRE říci, jestli výraz má být zpracován v režimu Unicode; pokud neřeknete nic, bude Unicode vypnuté. Jak přesně to PCRE říci je implementačně závislé:

    V editorech to obvykle neříkáte vůbec a zapnutí resp. nezapnutí podpory Unicode se řídí verzí příslušného editoru (tzn. u mého oblíbeného pluginu Regular Expressions Search And Replace pro FAR Manager si volíte, jestli chcete použít Unicode nebo ANSI verzi pluginu, a každá z verzí už má „natvrdo“ zapnutý nebo naopak vypnutý příznak „použít Unicode“). Fakticky se o to nemusíte starat jinak, než že při instalaci vyberete správnou verzi programu, všechno ostatní už běží automaticky.

    V programovacích jazycích se režim obvykle zapíná nebo vypíná ručně, obvykle při prvním použití toho kterého výrazu: funkce pcre_compile má mezi svými parametry i bitové pole příznaků (např. „nezáleží na velikosti písmen“ nebo „použij režim single-line“) a jedním z těchto příznaků je i příznak „vstupy jsou v Unicode“. Jen si musíte v dokumentaci dohledat, jak vlastně tento příznak předat. V PHP by se to například udělalo uvedením symbolu u v sekci modifikátorů:

    if (pcre_match('/^[0-9]+$/u', $text)) ...

    Zajímavé je, že v TPerlRegEx, asi nejlepší implementaci PCRE pro Delphi, se příznak nedá nastavit vůbec – komponenta si ho sama určí podle toho, jestli je zkompilována v Delphi s podporou Unicode (Delphi 2009 a výšší) nebo bez ní (všechny starší verze).

Poté, co splníte všechny výše uvedené podmínky, už PCRE k regulárním výrazům i k prohledávaným textům přistupuje jako textům v kódování Unicode, a to konkrétně ve variantě UTF8.

V Unicode režimu PCRE zpracovává všechny symboly, které jsme si dosud popsali, obdobným způsobem jako ve standardním režimu – liší se jen binární reprezentace, ne význam. Kromě toho ale přibylo několik nových symbolů, které jsou specifické pro Unicode a v „normálních“ regulárních výrazech nebudou fungovat.

Libovolný znak

Symbol \X je Unicodovou obdobou symbolu . (tečka) – reprezentuje jeden libovolný unicodový znak (přesněji řečeno grafém – po pravdě řečeno mi není úplně jasné, v čem se vlastně grafém od znaku liší). Rozdíl mezi \X a . je dán specifikací – . za normálních okolností říká „cokoliv kromě znaků CR a LF“ (viz druhý díl seriálu), naproti tomu \X znamená „cokoliv“ – včetně znaků pro konec řádku.

Symbol zadaný svým kódem

Podobně jako máme v základním PCRE symbol pro znak zadaný kódem (\x34 symbolizuje znak s hexadekadickým kódem 34, tj. v běžném ASCII kódování číslici čtyři), máme obdobný symbol i v Unicode variantě. Dokonce jsou tyto symboly dva: \u1234 a \x{1234} – oba reprezentují symbol s Unicode kódem 1234 hexadecimálně, rozdíl je v tom, že v první variantě \u musíme uvést vždy právě čtyři hexa číslice (tj. např. \u0034), zatímco ve verzi s \x{...} těch číslic může být uvedeno právě tolik, kolik je potřeba (tj. klidně \x{34} nebo \x{034}).

Symbol s danou Unicode vlastností (property)

Unicode znaková sada definuje pro každý znak jejich vlastnosti (property). Můžete je chápat jako kategorie nebo typy znaku – jedna z definovaných vlastností je „písmeno“ (letter), která se dělí na podskupiny „písmeno v malé abecedě“, „písmeno ve velké abecedě“ a některé další; jiná vlastnost definuje symboly, které dělí na matematické symboly, symboly měn atd.

Pomocí PCRE lze vyhledávat znaky, které mají nebo naopak nemají zadanou Unicode vlastnost, bez ohledu na použitou abecedu – můžete například vyhledat „velké písmeno“ bez ohledu na to, jestli to bude velké písmeno v češtině nebo v angličtině či v řečtině. Používá se pro to zápis \p{vlastnost} značící příslušnost ke skupině a \P{vlastnost} symbolizující opak (všechno jiného než znak se zadanou vlastností). Stačí jen vybrat si vlastnost.

Vlastností na výběr je celá řada, jejich kompletní přehled naleznete v Unicode dokumentaci k PCRE. Osobně jsem z nich nikdy nepotřeboval žádnou jinou než písmena (velká, malá nebo oboje):

  • L resp. Letter – libovolné písmeno.
  • Ll resp. Lowercase_Letter – písmeno malé abecedy.
  • Lu resp. Uppercase_Letter – písmeno velké abecedy.

… která se velmi hodí v situaci, kterou jsem popisoval ve druhém díle seriálu: Chci-li vybrat celá slova, nabízí se k tomu sice množinový zápis [a-z]+, jenže v češtině nepovede ke správnému výsledku, protože zahrnuje pouze písmena anglické abecedy, do které naše očárkovaná a oháčkovaná písmena nespadají. Pokud chcete vyhledat všechna slova v češtině (a ostatně i v jakémkoliv jiném jazyku, třeba v japonštině), je na to lepší použít Unicodový zápis využívající vlastností: \p{L}+ (chci jedna nebo více [radši více] po sobě jdoucích znaků s Unicode vlastností „letter“ [písmeno]).

Vhodnou kombinací jde udělat i složitější výrazy, např. „slova začínající velkým písmenem, u kterých jsou všechna následující písmena malá“: (?<!\p{L})\p{Lu}\p{Ll}*(?!\p{L}) (na začátku bude negativní look-behind na písmena [jinými slovy, bezprostředně před vyhledanou skupinou nesmí být písmeno], pak bude jedno písmeno velké abecedy, následovat bude libovolné množství písmen malé abecedy a na konci je negativní look-ahead na písmena [tzn. bezprostředně za vyhledanou skupinou nesmí být písmeno, malé ani velké]).

Podstatné je, že tento zápis bude fungovat v libovolném jazyce.

Symbol z daného Unicode skriptu (písma)

Znaková sada Unicode je dále rozdělena do řady bloků podle jednotlivých jazyků. Pro čečtinu bude nejpoužívanější skript Latin (latinská abeceda), ale může se hodit například Cyrillic (azbuka), pro matikáře nebo historiky Greek (řečtina) a pro příznivce Japan Shocku Hiragana a Katakana. Vybere si ale skoro každý.

Skripty se zapisují přesně stejně jako vlastnosti pomocí \p{skript} resp. \P{skript}, tj. například \p{Latin}+ (řetězec znaků latinské abecedy) nebo \p{Greek}{4} (čtyři po sobě jdoucí písmena řecké abecedy).

Seznam skriptů je opět v dokumentaci PCRE.

Symbol z daného Unicode bloku

Unicode bloky úzce souvisí se skripty, jsou ale detailněji členěné a orientované primárně na kódy než na skripty. Česká písmena například nalezneme v blocích Basic_Latin (kódy 00h až 7fh), Latin-1_Supplement (80h až ffh) a Latin_Extended-A (100h až 17fh). Zápis pro PCRE je pak ve tvaru \p{Inblok} a \P{Inblok}, tj. například \p{InBasic_Latin}+.

Seznam možných bloků si můžete nastudovat také v dokumentaci PCRE, osobně ale nevidím moc důvod, proč to vlastně dělat – za prvé, rozlišení podle skriptů je daleko jednodušší, a za druhé, neznám implementaci, která by Unicode bloky podporovala.

 

Unicode podpora pro PCRE se může velmi hodit, zejména bych doporučoval k zapamatování zápisy pro vyhledávání písmen, resp. znaků se zadanou vlastností. Jediný problém je podpora v programech – dokonce ani Programmer’s Notepad, který mi z editorů s podporou PCRE vychází nejlépe (tedy až po FARu s RESearch pluginem, pochopitelně, ale ten se kvůli nepodpoře pro zalamování řádek nehodí na úpravu delších textů), Unicode funkcionalitu nepodporuje (ve verzi 2.1.5).

Podobné příspěvky:

Leave a Reply

Themocracy iconWordPress Themes

css.php