A PCRE könyvtár függvények sorát tartalmazza, amelyek reguláris kifejezések mintaillesztését végzik el ugyanazt a szintaxist és szemantikát használva - néhány eltérést nem számítva -, mint a Perl 5. (lásd alább). A jelenlegi megvalósítás Perl 5.005-höz hasonló.
Különbségek Perl 5.005-höz képest:
1. Alapértelmezés szerint térköznek tekintendő minden olyan karakter, amit a C könyvtár isspace() függvénye felismer, bár lehetőség van arra, hogy PCRE-t eltérő karakterkódtáblázattal fordítsuk le. Az isspace() rendszerint a szóköz, lapdobás, "kocsi-vissza", újsor és vízszintes illetve függőleges tabulátorokat tekinti térköznek. Perl 5-ben ez utóbbi már nem szerepel a listában. A \v szekvencia nagyon sokáig benne volt a Perl dokumentációjában, valójában soha nem ismerte fel mintaillesztés közben. Legalább az 5.002 verzióig ezt a karaktert is térköznek tekintették, de a 5.004 és 5.005 verziókban már nem illeszkedik a \s-re.
2. PCRE nem engedi meg az előretekintő tesztekben (lookahead assertion) a kvantorok (sokszorozók) használatát. Perl-ben ez megengedett, de nem a várt eredményt adja. Például (?!a){3}, nem azt jelenti, hogy teszteli, vajon a következő három karakter nem "a", hanem azt, hogy háromszor "jelenti", ha a következő karakter nem "a".
Tagadó előretekintő tesztekben (negated lookahead assertion) szereplő "begyűjtő" részminták (capturing subpatterns) számon vannak tartva, de a hozzájuk tartozó numerikus változók soha nem kerülnek feltöltésre. Perl feltölti ezeket a numerikus változókat valamilyen, a sikertelen teszt előtti mintára illeszkedő részt követő karakterekkel, de csak akkor, ha a tagadó előretekintő tesztnek csak egy ága volt.
A bináris nullkarakter használata megengedett a tárgyszövegben, de a mintában nem, mert a mintául szolgáló sztring nullvégű C sztringként adódik át. A "\\x00" vezérlőszekvencia használható a mintában bináris nullkarakter megjelenítésére.
Nem támogatja az alábbi Perl vezérlőszekvenciákat: \l, \u, \L, \U, \E, \Q. Valójában ezek a funkciók a Perl sztringkezelő részében vannak megvalósítva, és nem tartoznak annak mintaillesztő motorjához.
A Perl \G tesztjét nem támogatja, mivel nem fontos az egyszeres minta illesztésekben.
Magától érthetődően PCRE nem támogatja a (?{kód}) szerkezetet.
A kézikönyv írása során néhány furcsaság még van a Perl 5.002_2-ben a begyűjtött sztringek feltöltésével kapcsolatban, ha a mintarészek ismétlődhetnek. Például, "aba"-ra illesztve a /^(a(b)?)+$/ mintát $2 numerikus változó értéke "b" lesz, míg a "aabbaa"-ra illesztve /^(aa(bb)?)+$/ -t $2 üres marad. Mindamellett /^(aa(b(b))?)+$/ -ra módosítva a mintát $2 és $3 is beállításra kerül. Perl 5.004-ben $2 mindkét esetben beállításra kerül, mint ahogy ez a PCRE-re is igaz. Ha a jövőben a Perl-ben ezt egységesíteni fogják, akkor PCRE követni fogja ezt.
Másik mindeddig megoldatlan eltérés, hogy pl. /^(a)?(?(1)a|b)+$/ minta Perl 5.002_2-ben illeszkedik a "a"-ra, míg PCRE-ben nem. Ráadásul mind Perl-ben mind PCRE-ben /^(a)?a/ minta "a"-ra illesztése során a $1 változó üresen marad.
PCRE néhény bővítést is nyújt a Perl reguláris kifejezéseinek lehetőségeihez:
Jóllehet a hátratekintő tesztek csak rögzített hosszúságú sztringekre illeszkedhetnek, az alternatív ágak mindegyikében különböző hosszúságú sztringre illeszkedő minta adható meg. Perl 5.005-ben minden ágban ugyanakkorának kell lennie ennek a hossznak.
Ha a PCRE_DOLLAR_ENDONLY be van kapcsolva, és a PCRE_MULTILINE nincs bekapcsolva, akkor $ metakarakter csakis a sztring legvégére illeszkedik.
Ha PCRE_EXTRA be van kapcsolva, akkor bármilyen külön jelentéssel nem bíró karakter előtti visszaperjel hibának minősül.
Ha PCRE_UNGREEDY be van kapcsolva, akkor a kvantorok (sokszorozók) mohóságát fordítva értelmezi, azaz, alapértelmezés szerint nem mohók, csak ha egy kérdőjel ? áll utánuk.
Az alábbiakban a PCRE által megvalósított reguláris kifejezések szintaktikáját és szemantikáját adjuk meg. A reguláris kifejezések leírása a Perl dokumentációnak része is, és néhány könyv is foglalkozik vele, némelyik rengeteg példával. Jeffrey Friedl "Mastering Regular Expression" c. könyve, amely az O'Reilly gondozásában jelent meg (ISBN 1-56592-257-3) igen nagy mélységben tárgyalja a reguláris kifejezéseket. Az itteni leírást referenciának szánjuk.
A reguláris kifejezés maga egy minta, amit a tárgyszövegre kell illeszteni balról jobbra. A karakterek többsége maga helyett áll a mintában, azaz csak saját magára illeszkedik a tárgyszövegben. Egy egyszerű példán bemutatva: az a gyors vörös róka minta a tárgyszöveg azon részére illeszkedik, ami megegyezik vele (azaz ahol az a gyors vörös róka előfordul).
A reguláris kifejezések ereje abban rejlik, hogy lehetőségünk van vagylagosságot (alternatívákat) és ismétléseket megadni a mintában. Ezeket a metakarakterek használatával lehet megadni, amelyek nem saját maguk helyett állnak a mintában, hanem speciális jelentéssel bírnak.
Két különböző típusú metakarakter létezik: az egyik bárhol előfordulhat a mintában, kivéve szögeletes zárójelek [] között, és a másik, ami csak szögeletes zárójelek között azonosítható metakarakterként. A szögletes zárójeleken kívüli metakarakterek:
több karakterből álló vezérlőszekvencia kezdetét jelzi
tárgyszöveg elejét (vagy sor elejét többsoros módban) jelenti
tárgyszöveg végét (vagy sor végét többsoros módban) jelenti
bármilyen karakterre illeszkedik, kivéve az újsor karaktert (alapértelmezés szerint)
karakterosztály definició kezdetét jelzi
karakterosztály definició végét jelzi
elágazás kezdetét jelzi
részminta kezdetét jelzi
részminta végét jelzi
opcionálitást jelez (0 vagy 1 előfordulást engedélyez), vagy kibővíti az előtte álló ( jelentését, és a kvantorok (sokszorozók) mohóságát befolyásolja
"0 vagy több" kvantor (sokszorozó)
"1 vagy több" kvantor (sokszorozó)
"min/max" kvantor (sokszorozó) kezdetét jelzi
"min/max" kvantor (sokszorozó) végét jelzi
több karakterből álló vezérlőszekvencia kezdetét jelzi
negálja az osztályt, kizáró / tagadó osztályt definiál, de csak ha ez az első karakter az osztályon belül
karaktertartományt jelez
lezárja a karakterosztályt
A visszaperjel \ karakternek számos alkalmazása van. Először is, ha nem alfanumerikus karakter követi, akkor annak bármilyen különleges jelentését (metakarakterek) figyelmen kívül hagyja, és azt mint maga helyett álló karaktert értelmezi. Ebben a minőségében mind karakterosztályon belül mind kívül használható.
Például, ha "*" karaktert kell illeszteni, akkor "\*"-t kell írni a mintában. Akármikor használható ez a szerkezet, akár a következő karakter egyébként metakarakterként lenne értelmezve, akár nem. (Egy kivétel van lásd a ] karakternél - a fordító.) Ezért biztos módszer előírni azt, hogy minden nem alfanumerikus karakter maga helyett álljon, úgy, hogy visszaperjelet (\) írunk elé. Különben ha a visszaperjelre szeretnénk illeszteni, akkor "\\"-t kell írni.
Ha a minta PCRE_EXTENDED módosítóval van megadva, akkor minden olyan térközkaraktert figyelmen kívül hagy, amely karakterosztályon kívül vagy karakterosztályon kívüli "#" és azt követő újsor-karakter között szerepel. Visszaperjellel bevezetett térköz- vagy "#" karakterek a minta részét képezik.
A visszaperjel másik alkalmazása a nem nyomtatható karakterek kódolását teszi láthatóvá a mintában. Nincs megszorítás a nem nyomtatható karakterek megjelenésére, kivéve a mintát lezáró nullkaraktert. Ha a minta szövegszerkesztés folyományaként áll elő, akkor általában könnyebb valamelyik alábbi vezérlőszekvenciát használni, mint az általuk reprezentált karakter bináris alakját:
csengő karakter (hexadecimálisan 07)
"control-x", ahol x bármilyen karakter lehet
"escape" (hexadecimálisan 1B)
lapdobás (hexadecimálisan 0C)
újsor (hexadecimálisan 0A)
kocsivissza (hexadecimálisan 0D)
tabulátor (hexadecimálisan 09)
hh hexadecimális kódú karakter
ddd oktális kódú karakter, vagy "hivatkozás"
A "\cx" feloldása precízen megfogalmazva a következő: ha "x" kisbetű, akkor nagybetűvé konvertálódik. Ezután a karakter 6. bitjét (hexadecimálisan 40) invertálja. Ilyenformán "\cz"-ból hexadecimális 1A lesz, de "\c{"-ból hexadecimális 3B lesz, míg "\c;"-ból hexadecimális 7B.
A "\x" után két hexadecimális számjegy kerül beolvasásra (a betűk lehetnek kis és nagybetűk is).
A "\0" után két további oktális számjegy kerül beolvasásra. Minden esetben - még ha kevesebb, mint két számjegy került is megadásra - a meglevő számjegyek lesznek felhasználva. Ekképpen "\0\x\07" egy olyan sorozatot definiál, ahol két bináris nullkaraktert követ egy csengőkarakter. Bizonyosodj meg affelől, hogy mindig van két számjegy a kezdő 0 után, ha a következő karakter oktális számjegy!
A nem 0-val folytatódó visszaperjel kezelése bonyolult. Karakterosztályon kívül PCRE ezt és a soron következő számjegyeket tízes számrendszerbeli számként értelmezi. Ha szám 10-nél kisebb vagy legalább ezzel a számmal egyező "gyűjtő" nyitó zárójel előzi meg a kifejezésben, akkor az egész sorozatot hivatkozásként értelmezi. Később a zárójelezett részminták fejezetében részletesen tárgyaljuk, hogyan használható is ez.
Karakterosztályon belül vagy ha a tízes számrendszerbeli szám 9-nél nagyobb, és nincs ennyi számú "gyűjtő" részminta, akkor PCRE újraolvassa a visszaperjelet követő három oktális karaktert, és egy bájtra váltja a 8 legkisebb helyiértékű bitet. Bármely rákövetkező számjegy maga helyett áll, magára illeszkedik.
egy másik módja a szóköz megadásának
ugyanaz mint előbb, ha biztosított, hogy 40-nél kevesebb "gyűjtő" részminta van előtte
mindig hivatkozásként értelmezi
hivatkozás is lehet, vagy a tabulátort írhatjuk így
mindig tabulátort jelent
tabulátor és utána egy "3"
113-as oktális kódú karakter ("K"), mivel hivatkozások száma nem lehet több, mint 99
egy olyan bájt, ami teljes egészében 1 értékű biteket tartalmaz
akár hivatkozás is lehet, vagy egy bináris nullkarakter és utána két karakter egy "8" és egy "1"
Figyelj arra, hogy 100-nál nagyobb oktális értékek elé nem szabad bevezető 0-t írni, mert mindig csak három oktális kerül beolvasásra.
Minden sorozat, ami egy egyszerű bájtot határoz meg, karakterosztályon belül és kívül is használható. Ráadásul karakterosztályokon belül a "\b" szekvencia "visszatörlés" karakterként (backspace) (hexadecimálisan 08) jelent. Ennek karakterosztályokon kívül más jelentése van (lásd alább).
A visszaperjel harmadik alkalmazási módja általános karakterfajták megadása:
bármilyen tízes számrendszerbeli számjegy (decimális)
bármilyen karakter, ami nem tízes számrendszerbeli számjegy
bármilyen térközkarakter
bármilyen nem térközkarakter
bármilyen "szóépítő" karakter
bármilyen nem "szóépítő" karakter
Mindegyik szekvenciapár két diszjunkt (egymással nem átfedő) részre osztja a karakterek teljes halmazát. Minden karakter csakis a párok egyik felébe tartozik.
"Szóépítő" karakter minden betű vagy számjegy vagy aláhúzás, azaz minden olyan karakter, amit egy Perl-típusú "szónak" része lehet. A betűk és számjegyek értelmezése a PCRE karaktertáblázataitól függ, amelyek változhatnak ha nyelvi beállítástól függően. Például, "fr" (vagy "hu" - a fordító) nyelvi beálllítás esetén 128-nál magasabb kódú karakterek használatosak az ékezetes betűkhöz, amelyekre illeszkedik a \w.
Ezek a karakterfajták mind karekterosztályokon belül és kívül is alkalmazhatók. Mindegyik csak egy, a neki megfelelő karakterre illeszkedik. Ha az aktuális illeszkedési pont a tárgyszöveg vége, akkor mindegyik sikertelen lesz, mert egyáltalán nincs karakter, amire illeszteni lehetne.
A visszaperjelet végül de nem utolsósorban néhány egyszerű teszt megadására használhatjuk. A tesztek (assertion) olyan feltételek, amelyeknek az illesztés adott pontján kell teljesülnie anélkül, hogy a tárgyszöbegből karaktereket használnának el - és így karaktereket vennének el az illesztéstől. Később megadjuk, hogy hogyan használhatók a részminták összetettebb tesztek megadásához. A "visszaperjeles" tesztek:
szóhatár
nem szóhatár
tárgyszöveg kezdete (függetlenül többsoros üzemmódtól)
tárgyszöveg vége vagy újsor karakter a végén (függetlenül többsoros üzemmódtól)
tárgyszöveg vége (függetlenül többsoros üzemmódtól)
Ezek a tesztek karakterosztályokban nem használhatók. (Figyeld meg, hogy "\b"-nek eltérő jelentése van karakteroszályokon belül, nevezetesen itt a "visszatörlés" karakter helyett áll.)
A szóhatár a tárgyszöveg azon poziciója, ahol az aktuális és az azt megelőző karakterek fajtája \w illetve \W vagy fordítva (az egyik \w-re illeszkedik, míg a másik \W-re), vagy a tárgyszöveg eleje illetve vége, ha az első illetve utolsó karakter a \w-re illeszkedik.
A \A, \Z és \z tesztek különböznek a hagyományos kalap(os ékezet) "^" és dollárjel "$" szimbólumoktól, mert az előbbiek minden esetben csakis a tárgyszöveg legelejére illetve legvégére illeszkednek. Nem befolyásolja a viselkedésüket sem PCRE_NOTBOL sem PCRE_NOTEOL módosító. A \Z és \z közti különbség annyi, hogy a \z csak a tárgyszöveg végére illeszkedik, míg \Z az esetlegesen a tárgyszöveg végén lévő újsor karakter előtt is.
Karakterosztályokon kívül az alapértelmezett illesztési
üzemmódban a kalap(os ékezet) egy olyan tesztet jelent,amely
csak akkor és csak is akkor igaz (TRUE), ha a pillanatnyi
illesztési pont a tárgyszöveg kezdete. Karakterosztályokon
belül teljesen más jelentése van (lásd alább).
A kalapnak akkor nem szükséges a minta legelején állnia, ha
több választási lehetőség is fennáll (lásd: retesz pipa
csővezeték |), de minden választható ágban a legelsőnek kell
lennie, ha azt akarod, hogy a minta valaha is illeszkedjen.
Ha mindegyik lehetséges ág "kalappal" kezdődik, azaz ha a
minta mindenesetben csak a tárgyszöveg elejétől kezdve
illeszkedhet, akkor "(le)rögzített" mintáról beszélünk.
(Más módja is van, hogy egy mintát "rögzíts".)
A dollárjel olyan tesztet jelent, amely csak akkor és csakis
akkor igaz (TRUE), ha a pillanatnyi illesztési pont a
tárgyszöveg vége vagy egy újsor karakter előtti pozició - az
alapértelmezés szerint. A dollárjelnek akkor nem szükséges a
minta legvégén állnia, ha több választási lehetőség is fennáll
(lásd: retesz pipa csővezeték |),de minden választható ágban
- ahol szerepel - a legutolsónak kell lennie. A dollárjelnek
nincs külön jelentése karakterosztályokon belül.
A dollárjel jelentése megváltozik és csak a tárgyszöveg
végére illeszkedik, ha a PCRE_DOLLAR_ENDONLY módosító be van
kapcsolva a minta fordításakor / kiértékelésekor vagy az
illesztés pillanatában. Ez nem érinti a \Z tesztet.
A kalap(os ékezet) és a dollárjel jelentését megváltoztatja
PCRE_MULTILINE módosító bekapcsolása. Ebben az esetben a
közbenső "\n" újsorkarakterek közvetlen előtti illetve utáni
pozicióira is illeszkednek a tárgyszöveg eleji és végi
pozición felül. Például, így a /^abc$/ minta többsoros
üzemmódban illeszkedik a "def\nabc" szövegre, de egyébként
nem. Következésképpen az egysoros üzemmódban "rögzítettnek"
tekintett minták, nem "rögzítettek" többsoros üzemmódban,
mert ekkor "^"-kal kezdődő vagylagos ágak nem tekinthetők
"rögzítettnek". A PCRE_DOLLAR_ENDONLY módosítót figyelmen kívül hagyja, ha a
PCRE_MULTILINE, módosító be van kapcsolva.
Figyelj arra, hogy a \A, \Z és \z szekvenciák mindkét
üzemmódban használhatók a tárgyszöveg elejére illetve végére
illesztésben, és ha minden vagylagos ág \A -val kezdődik,
akkor a minta mindig "rögzített" lesz akármi is a
PCRE_MULTILINE módosító állapota.
Karakterosztályokon kívül a pont bármelyik karakterre
illeszkedik beleértve minden nem nyomtatható karaktert is,
kivéve az újsort - alapértelmezés szerint. Ha a PCRE_DOTALL
be van kapcsolva, akkor az újsor karakterre is illeszkedik.
A pont kezelése teljesen független a kalap(os ékezet) ^ és
a dollárjel $ kezelésétől, az egyetlen közös hármukban, hogy
mindegyiknek köze van az újsor karakterhez. A pontnak nincs
speciális jelentése karakterosztályokon belül.
A nyitó szögeletes zárójel egy karakterosztály kezdetét, míg
a záró párja annak végét jelzi. A bezáró zárójel önmagában
nem hordoz speciális jelentést. Ha egy ] karaktert kell a
karakterosztályon belül megadni, akkor annak vagy legelöl
kell állnia - az esetleges kalap(os ékezet) után -, vagy egy
visszaperjelet kell eléírni.
A karakterosztályok csak a tárgyszöveg egyetlen karakterére
illeszkednek. Ha a karakterosztály legelső karaktere nem a
kalap(os ékezet) ^,akkor ez csak a karakterosztályba tartozó
karakterek valamelyikére illeszkedik, ha a legelső karakter
kalap(os ékezet) ^ , akkor pedig csak azokra, amelyek nem
elemei az osztálynak. (Ez utóbbit hívjuk tagadó vagy kizáró
karakterosztálynak - a fordító.) Ha a kalap(os ékezet) ^
karaktert kell megadni egy karakterosztály elemeként, akkor
az nem lehet a legelső pozicióban, vagy visszaperjelet kell
eléírni.
Az [aeiou] karakterosztály például minden kisbetűs ékezet
nélküli magánhangzóra illeszkedik, míg az [^aeiou] pont
ezekre nem. A kalap(os ékezet) kényelmes jelölési forma olyan
karakterosztályok megadására, ahol a kizárandó elemeket
könnyebb felsorolni. Ez nem teszt, ez karaktereket használ
el a tárgyszövegből, ezért a tárgyszöveg végén az illesztés
sikertelen lesz.
Amikor a kis- és nagybetűk különbözősége nem számít, akkor a
betűk a kis- és nagybetűs alakjukat is képviselik, tehát
ilyen esetben például [aeiou] illeszkedik az "A"-ra és az
"a"-ra is, és az [^aeiou] nem illeszkedik a "A"-ra, csak ha
a kis- és nagybetű különbözősége számít.
Karakterosztályokban az újsort soha nem kezelik különleges
módon, bármi is a PCRE_DOTALL és a PCRE_MULTILINE módosító
értéke. A kizáró karakterosztályok - mint pl.: [^a] - pedig
mindig illeszkednek az újsor karakterre.
Az "-" elválasztójellel karaktertartományokat lehet megadni
a karakterosztályon belül. A [d-m], például, a d és m közti
bármelyik karakterre illeszkedik - d-t és m-et is beleértve.
Ha az elválasztójelet kell a karakterosztályon belül megadni,
akkor vagy egy visszaperjelet kell eléírni, vagy olyan
pozicióban kell megadni, ahol nem lehet tartományképzőként
értelmezni, jellemzően a karakterosztály első vagy utolsó
tagjaként.
A "]" karaktert ebben a literális formában nem lehet egy
tartomány záró tagjaként használni. A [W-]46] minta például
azt jelenti, hogy a "W" és "-" karakterek valamelyikét
kövesse a "46]" sztring, ezért a "W46]" vagy a "-46]"
illeszkedik a mintára. Ha azonban visszaperjelet írunk elé,
akkor a visszaperjel lesz a tartomány felső határa, és ekkor
"[W-\]46]" mintát egy egyszerű osztályként értelmezi, amit
három különálló karakter követ. Oktális vagy hexadecimális
ábrázolásban lehet megadni a "]"-t mint tartományt lezáró
karaktert.
A tartományok meghatározásakor az ASCII karaktertáblázat
karakterkódjai számítanak. A karakterek helyett a numerikus
kódjaik is használhatók, például [\000-\037]. Ha kis- és
nagybetűkre nem érzékeny az illesztés és a tartomány betűket
is felölel, akkor azok mind a kis- mind a nagybetűs
alakjuknak megfelelő karaktereket egyaránt helyettesítik,
például a [W-c] ugyanaz, mint a [][\^_`wxyzabc] , és ha a
"fr" nyelvi beállítást használjuk, akkor a [\xc8-\xcb] minta
illeszkedik minden ékezetes e illetve E karakterre.
(franciában van pár ilyen :)
A karakterosztályokhoz karakterfajtákat - \d, \D, \s, \S, \w
és \W -t - is hozzáadhatunk, és így a fajtába tartozó
karaterekkel bővíthejük. A [\dABCDEF] - például - minden
hexadecimális számjegyre illeszkedik . A kalap(os ékezet)-t
a nagybetűs (tagadó) fajtákkal együtt használva kényelmesen
megadható a kisbetűs párjuknál korlátozotabb halmaz.A [^\W_]
karakterosztály minden betűre és számjegyre illeszkedik, de
az aláhúzásra nem (ami ugyancsak eleme a \w-nek).
A \, -, a kezdő ^ és a záró ] karakterektől eltekintve a
nem alfanumerikus karaktereknek nincs különleges jelentésük
a karakterosztályokon belül, de nem okoz gondot, ha esetleg
visszperjel előzi meg ezeket.
A "|" karakterrel vagylagos - alternatív - mintákat lehet
megadni, pontosabban azokat választja el egymástól. Például
gyula|sacika
minta illeszkedik a "gyula" és a "sacika" szövegre is.
Bármennyi vagylagos mintát fel lehet sorolni, köztük az üres
mintát is, ami az üres sztringre illeszkedik. Az illesztés a
mintákat balról jobbra, egymás után sorjában veszi, és a
legelső sikeresen illesztett lesz használva. A részmintákban
használt vagylagos ágak esetében a "sikeresen" azt jelenti, a
minta fennmaradó részét is sikerül illeszteni.
A PCRE_CASELESS , PCRE_MULTILINE , PCRE_DOTALL és
PCRE_EXTENDED módosítókat a minta belsejében is átállíthatjuk
"(?" és ")" közé írt Perl-beli betűjelzéseikkel. Ezek a betűk:
i = PCRE_CASELESS
m = PCRE_MULTILINE
s = PCRE_DOTALL
x = PCRE_EXTENDED
A "(?im)" bekapcsolja a többsoros és a "kis-nagybetű mindegy"
üzemmódot. Kikapcsolni az egyes beállításokat az eléjük írt
kötőjellel lehet. Ezenkívül a módosítók együttes állítása is
megengedett, például a (?im-sx) bekapcsolja a PCRE_CASELESS-t
és a PCRE_MULTILINE-t valamint kikapcsolja PCRE_DOTALL-t
és PCRE_EXTENDED-t. Ha egy betűjelzés a kötőjel mindkét oldalán
szerepel, akkor a módosító ki lesz kapcsolva.
Ezeknek a beállításoknak az érvényességi köre attól függ,
hogy a mintán belül hol fordulnak elő. Minden részmintán
kívüli beállítás olyan, mintha az illesztés kezdetén lett
volna megadva, ezért a következő minták tökéletesen ugyanúgy
működnek:
(?i)abc
a(?i)bc
ab(?i)c
abc(?i)
, ami ugyanaz, mintha az "abc" mintát PCRE_CASELESS módosítóval
adtuk volna meg. Másszóval a legfelső szintű beálllítások az
egész mintára érvényesek, hacsak egy részmintában felül nem
bírálod azokat. Ha a módosítónak több beállítása is szerepel
a legfelső szinten, akkor a jobbról legutolsó fog érvényre
jutni.
Ha részmintán belül történik módosítóváltoztatás, akkor a
hatás különböző (Perl 5.005 viselkedésbeli változása).
A részmintán belüli módosító-állítás csak a részminta
hátramaradó részét érinti, ezért
(a(?i)b)c
minta csak az "abc" és "aBc" szövegekre illeszkedik feltéve,
hogy PCRE_CASELESS módosítót nem adtuk meg. Ez azt
jelenti, hogy a minta különböző helyein a módosítók más és
más értékeit lehet beállítani. Bármilyen változtatás egy
vagylagos (választható) ágban a következő ágakra is hatással
van ugyanabban a részmintában, például
(a(?i)b|c)
minta illeszkedik az "ab", "aB", "c" és "C" szövegekre még
akkor is, ha "C"-re illeszkedve az nem is az első ágra esett
a választás, ahol a módosító be lett állítva. Ennek az az
oka, hogy a módosító beállítások hatásai már a kifejezés
fordításakor / kiértékelésekor rögzülnek, máskülönben néha
nagyon furcsa viselkedést tapasztalhatnánk.
A PCRE-specifikus PCRE_UNGREEDY és PCRE_EXTRA módosítókat
a Perl-kompatibilisekhez hasonló módon állíthatók, az U és X
karakterek használatával.A (?X) beállítás különleges, mert -
még a legfelső szinten is - mindig hamarabb kell szerepelnie
a mintában, mint a további kapcsolóknak. Legjobb a minta
legelejére rakni.
A részminták egymásba ágyazhatók, és kerek zárójel fogja
közre őket. A minta egy darabját részmintaként szerepeltetni
két dolgot jelent:
1. Elágazási lehetőségek helyét jelöli ki (csoportosítás):
szél(toló|kakas|)
minta illeszkedik a "szél", "széltoló" vagy "szélkakas"
szavak egyikére. Zárójel nélkül a "széltoló"-ra, a "kakas"-ra
vagy az üres sztringre illeszkedne.
2. A részmintát "gyűjtő" részmintává változtatja. Ha a
teljes mintát sikerült illeszteni, akkor a tárgyszöveg azon
részei, amelyek a "gyűjtő" részmintákra illeszkedtek,
a pcre_exec() függvény ovector paraméterében a hívó
függvénynek lesznek átadva.
A kerek nyitó zárójelek számozása balról jobbra 1-től kezdve
történik, és "gyűjtő" részminták (sor)számát adják.
Például, ha az "a vörös király" szöveget illesztjük
a ((vörös|sápadt) (király|királynő))
mintára, akkor a megtalált / begyűjtött szövegrészek :
1. "vörös király", 2. "vörös" és 3. "király".
Az a tény, hogy a kerek zárójelnek kettős szerepe van, nem
minden esetben hasznos. Sokszor előfordulhat, hogy csak a
csoportosító funkcióra van szükségünk "begyűjtés" nélkül.
Erre szolgál a nyitó zárójel után irható "?:" karaktersorozat
, mert ekkor a részminta nem gyűjti be / tárolja el a
ráilleszkedő szövegrészt, és nem is számít bele a következő
"gyűjtő" részminták sorszámozásába. Az előző példánál maradva
"a sápadt királynő"
a ((?:vörös|sápadt) (király|királynő))
mintára illesztve a megtalált / begyűjtött részminták :
1. "sápadt királynő" és a 2. "királynő".
A "gyűjtő" részminták száma legfeljebb 99 lehet,és az összes
részminta "gyűjtő" és "nem-gyűjtő" együtt legfeljebb 200.
Ha egy nem-gyűjtő részminta elején módosítókat kell állítani,
akkor kényelmes rövidítésként használható, hogy a módosítók
betűjelei a "?" és a ":" közé írhatók. Ebből adódóan az
alábbi két minta
(?i:szombat|szerda)
(?:(?i)szombat|szerda)
pontosan ugyanazokra a sztringekre illeszkedik.
Mivel a vagylagos / választható ágak próbálgatása balról
jobbra történik, és a módosító hatása addig él, amíg a
részminta le nem zárul, az egyik ágban beállított módosító
hatással van a következő ágra is, ezért a fenti minta
illeszkedik a "SZERDA" és "Szombat" szavakra is.
Az ismétléseket kvantorokkal (sokszorozókkal) lehet megadni
a következő poziciók után:
egyszerű karakter (esetleg visszaperjellel bevezetve),
. metakarakter,
karakterosztály,
hivatkozás (ld. következő szakasz) vagy
zárójeles részminta (nem teszt)
után.
Az általános ismétlő kvantor (sokszorozó) - kapcsos
zárójelben vesszővel elválasztva - írja elő azt minimális és
maximális előfordulási számot, ahányszor a mintát illeszteni
kell illetve lehet. Ezeknek 65536-nél kisebbnek kell lenniük,
és az első legfeljebb annyi lehet, mint a második. Például a
z{2,4}
minta illeszkedik a "zz", "zzz" vagy "zzzz" szövegekre.
Az egymagában álló záró kapcsos zárójel nem bír speciális
jelentéssel. Ha a második számot nem adjuk meg, de a vessző
szerepel, akkor az illesztésnek nincs felső határa, de ha a
vesszőt is elhagyjuk, akkor a kvantor (sokszorozó) pontosan
a megadott számú illesztést engedi csak. Ekképpen:
[aáeéiíoóöőuúüű]{3,}
legalább 3 egymást követő magánhangzóra illeszkedik, de akár
többre is, míg a
\d{8}
csakis 8 darab számjegyre. Ha a nyitó kapcsos zárójel olyan
helyen szerepel, ahol kvantor nem szerepelhet, akkor betű
szerint lesz figyelembe véve, maga helyett áll a mintában. A
{,6} például nem kvantor (sokszorozó), hanem egy négy
karakteres minta betű szerint értelmezve.
A {0} kvantor (sokszorozó) megengedett, és hatása olyan,
mintha az előtte álló mintaelem és maga a kvantor nem is
szerepelne.
Kényelmi és történelmi okokból három, gyakori kvantornak
létezik rövidítése is:
* egyenlő a {0,} - val
+ egyenlő a {1,} - val
? egyenlő a {0,1} - val
Végtelen ciklusokat is lehet definiálni úgy, ha egy olyan
részmintát sokszorozzunk felsőhatár nélkül, amelynek nem
muszáj illeszkednie egyetlen karakterre sem, például:
(a?)*
Perl és PCRE korábbi verziói hibát jeleztek az ilyen minták
kiértékelésekor / fordításakor. Azonban vannak esetek,amikor
ezek a minták is hasznosak lehetnek, ezért ezeket a mintákat
most már elfogadják, de ha a részminták ismételten nem
illeszkednek egy karakterre sem, a ciklust erőszakkal
megszakítják.
Alapértelmezés szerint a kvantorok (sokszorozók) "mohók" ,
azaz amennyi karakterre csak illeszteni tudnak, azt mind
elhasználják a tárgyszövegből a felső határ figyelembe vétele
mellett és anélkül, hogy a minta többi része sikertelenül
illeszkedne.
A klasszikus példa, ahol ez problémát okoz, a C forráskódok
megjegyzéseire illeszkedő kifejezés. Ezek a megjegyzések nem
egymásba ágyazhatók, /* és */ közé írt tetszőleges szövegek,
amelyekben szerepelhet a * és / jel is (nem egymás mellett).
/\*.*\*/
mintát a
/* első megjegyzés */ c_code(); /* második megjegyzés */
C forrásrészletre illesztve kudarcot vallunk - köszönhetően
a .* elem mohóságának. (Az illesztés sikeres, csak nem arra
való, amire szerettük volna - a fordító).
Ha azonban a kvantort (sokszorozót) kérdőjel ? követi, akkor
ez megszünteti annak mohóságát, és csak a lehető legkevesebb
illesztést engedi, ezért a
/\*.*?\*/
minta az, ami C forráskódú megjegyzésekre való. A különböző
kvantorok (sokszorozók) jelentése egyébként nem változik
ettől, csak az előnyben részesített illeszkedési számuk. A
kérdőjelnek ez a szerepe nem összetévesztendő a feltételes
kvantorral (sokszorozóval), mert a kérdőjelet kétféleképpen
és néha megkettőzve használjuk, például:
\d??\d
egy számjegyre illeszkedik leginkább, és csak akkor kettőre,
ha a minta maradék része másképp nem illeszkedne.
Ha a PCRE_UNGREEDY módosító be van kapcsolva, akkor
a kvantorok (sokszorozók) alapértelmezés szerint nem mohók
(szerények :), csak ha egykérdőjel követi őket. Másszóval, a
kérdőjel átállítja a kvantorok alapértelmezés szerinti
viselkedését.
Amikor egy zárójelezett részminta egynél többször vagy
legfeljebb meghatározott számban ismétlődhet, akkor a
kiértékelt minta több memóriát foglal el a minimális és
maximális előfordulással arányosan.
Ha a minta .* -val vagy .{0,} -val kezdődik és a PCRE_DOTALL
módosító (Perl-beli /s-nek megfelelője) be van kapcsolva, és
így a . illeszkedik az újsor karakterre is, akkor a minta
hallgatólagosan "rögzített" lesz, mert bármi is következik
utána, az a tárgyszöveg minden karakterpoziciójára "rá lesz
próbálva", így nincs az elsőn kívül más karakterpozició,
ahonnan az egész illesztés újrakezdődhetne. PCRE az ilyen
mintákat úgy tekinti, mintha \A-val kezdődne. Azokban az
esetekben, amikor tudjuk, hogy a tárgyszöveg nem tartalmaz
újsorkaraktereket és a minta .* -gal kezdődik, érdemes
beállítani a PCRE_DOTALL módosítót vagy ^ -t használni
a "rögzítés" eléréséhez, hogy ezt az optimalizálást
kieszközöljük.
Ha a "(be)gyűjtő" részminta az illesztés során ismételten
felhasználásra kerül, akkor a begyűjtött / megtalált szöveg-
rész az utolsó ismétlésben illeszkedő rész lesz. Például a
(csori[keat]{3}\s*)+
minta a "csorikea csoriaet" történő illesztése után a
begyűjtött / megtalált szövegrész "csoriaet" lesz. Egymásba
ágyazott részminták esetén a begyűjtött érték lehet, hogy az
előző lépésben lett beállítva, például:
/(a|(b))+/
illesztve a "aba" -ra a második begyűjtött szövegrész a "b".
Karakterosztályon kívül visszaperjelet követő számjegy(ek) a
mintában korábban előforduló "gyűjtő" részmintára történő
hivatkozásnak minősül(nek), ha a számnak megfelelő "gyűjtő"
részminta nyitó kerek-zárójele ( előfordult már a mintában.
Ha azonban ez a tízes számrendszerbeli szám 10-nél kisebb,
akkor mindig hivatkozásnak minősül, s csak akkor okoz hibát,
ha nincs ennyi "gyűjtő" részminta megnyitva az egész mintán
belül. Magyarán a 10-nél kisebb sorszámú kerek nyitó
zárójeleknek nem kell a hivatkozás előtt, a mintában ettől
balra állniuk. Olvasd el a "visszaperjel \" szakaszt, ahol
részletesen olvashatsz arról, hogy miképpen kezeli a PCRE a
visszaperjel után álló számjegyeket.
A hivatkozások az általuk megcímzett "gyűjtő" részmintákra
ténylegesen illeszkedő szövegrészeket testesítik meg, és nem
azokat, amelyre illeszkedhettek volna egyébként. Mindjárt
megvilágítjuk egy példán keresztül:
(ért|kegy) és \1elem
illeszkedik a "kegy és kegyelem"-re és "ért és értelem"-re,
de nem illeszkedik az "ért és kegyelem"-re.
Ha a kis- és nagybetűk különbsége érvényben van a hivatkozás
pillanatában, akkor számít a betűalakok különbsége. Például
((?i)rah)\s+\1
minta illeszkedik a "rah rah" és "RAH RAH" szövegekre, de a
"RAH rah" -ra még akkor sem, ha az eredeti "gyűjtő"
részmintában a kis- és nagybetűk különbsége nem számított.
Egy részmintára több hivatkozás is utalhat. Ha a részminta
ténylegesen nem lett felhasználva az illesztés során, akkor
bármilyen hivatkozás rá hibát jelent. Például
(a|(bc))\2
minta mindig hibázik, ha az illesztés "a"-val kezdődött és
nem "bc"-vel.Mivel legfeljebb 99 hivatkozás lehet egy mintán
belül, minden visszaperjel után álló számjegy egy lehetséges
hivatkozás részét képezheti. Ha a mintát számjeggyel
kellene folytatni, akkor a hivatkozás végét valamilyen
elválasztókarakterrel kell jelezni. Ha PCRE_EXTENDED módosító
be van kapcsolva, akkor ez bármilyen térközkarakter lehet,
egyébként egy üres megjegyzés is megfelel.
Azok a hivatkozások, amelyek magára a hivatkozást tartalmazó
részmintára utalnak,a részminta első illesztésekor hibáznak,
ezért például (a\1) soha nem illeszkedik semmire. Azonban az
ilyen hivatkozások is értelmet nyerhetnek, például az alábbi
minta
(a|b\1)+
illeszkedik a csupa "a"-ból álló és az "aba", "ababaa" s
ehhez hasonló sorozatokra. A részminta illesztés minden
iterációjában a hivatkozás az előző iterációnak megfelelő
karaktersorozatra utal. Azért, hogy ez működjön, a mintának
olyannak kell lennie, hogy az első lépésben nem kelljen a
hivatkozásnak illeszkednie.Ez vagylagos ágak vagy elhagyható
- minimálisan 0 ismétlést előíró - kvantor (sokszorozó)
használatával megoldható.
Angolul "assertion"-nek nevezett szerkezet olyan tesztet
vagy feltételt jelent, ami a pillanatnyi illesztési pozició
előtti vagy utáni karakterekre vonatkozik, de ténylegesen
nem használ el karaktereket a tárgyszövegből az illesztés
elől, csak ellenőrzi egy feltétel fennállását. Az egyszerű
teszteket - \b, \B, \A, \Z, \z, ^ és $ - már tárgyaltuk.
Az ennél bonyolultabbakat részmintaként kell megadni.Kétféle
teszt van: az előretekintő, ami a pillanatnyi illesztési
pozició utáni karaktereket vizsgálja, és a hátratekintő, ami
az az előttieket.
A teszt részmintája a szokásos módon illeszkedik, attól
eltekintve, hogy a pillanatnyi illesztési poziciót nem
változtatja meg. Az előretekintő tesztek "(?=" vagy tagadó
feltétel esetén "(?!" sorozattal kezdődnek, például
\w+(?=;)
illeszkedik minden szóra, amelyet pontosvessző követ, de a
pontosvessző nem szerepel az illeszkedésben, és az
ize(?!bigyo)
illeszkedik a "ize" minden olyan előfordulására, amit nem a
"bigyo" követ. Nyilvánvaló, hogy egy hasonló minta
(?!ize)bigyo
nem azokat a "bigyo"-kat találja meg, amelyek előtt nem "ize"
van; hanem minden "bigyo"-t megtalál, mert a (?!ize) teszt
mindig igaz, hiszen az utána jövő három karakter tényleg nem
"ize", hanem "big" (tesztként nem változik a pillanatnyi
illesztési pozició - a fordító). Ahhoz, hogy a kívánt hatást
érjük el a hátratekintő tesztre van szükségünk.
A hátratekintő tesztek (?<= vagy tagadó feltétel esetén
a (?<! sorozattal kezdődnek, például
(?<!ize)bigyo
azokat a "bigyo"-kat találja meg, amelyek előtt nincs "ize".
A hátratekintő tesztek csak rögzített hosszúságúak lehetnek.
Ha azonban több alternatívát adunk meg a teszten belül,
a különböző ágaknak lehet eltérő a hossza, ilyenformán a
(?<=tulok|szamár)
megengedett, ellentétben a
(?<!kutyus(ok)?|macsk(ák)?)
mintával, amely kiértékelés / fordítás során hibát okoz.
Az eltérő hosszúságú ágtesztek a hátratekintő tesztek
legfelső szintjén megengedettek. Ez PCRE bővítés a Perl
5.005-höz képest,ahol minden ágtesztnek azonos hosszúságúnak
kell lennie. A
(?<=ab(c|de))
mintához hasonlók nem megengedettek, mert a legfelső szinten
levő egyetlen ág két különböző hosszúságú szövegre is
illeszkedhet, de átírható, hogy a vagylagosságot a felső
szintre emeljük:
(?<=abc|abde)
A hátratekintő tesztek megvalósítása a következő: minden
ágra a pillanatnyi illesztési pozició átmenetileg hátrébb
kerül az ágtesztnek megfelelő számú karakterrel és ezután
illeszteni próbál. Ha nincs elég karakter a visszalépéshez,
az illesztés sikertelen lesz. A hátratekintő tesztek az
egyszeri részmintákkal együtt különösen hasznosak lehetnek
a szöveg végi illeszkedéseknél, az "Egyszeri részminták" c.
szakasz végén található erre példa.
Számos különböző fajtájú teszt állhat egymás után, például:
(?<=\d{3})(?<!999)ize
minta azokra az "ize"-kre illeszkedik, ami előtt 3 számjegy
áll, amely nem a "999". Figyelj arra, hogy minden teszt
egymástól függetlenül, ugyanabban az illesztési pozicóban
kerül kiértékelésre. Először azt ellenőrzi, hogy a megelőző
három karakter számjegy-e és utána azt, hogy ezek nem a
"999"-t adják.Ez a minta nem azokra az "ize"-kre illeszkedik,
amelyek előtt hat karakter áll: három számjegy és másik
három, ami nem a "999", példaképpen nem illeszkedik a
"123abcize" szövegre. Az a minta, ami ezt tudja a következő:
(?<=\d{3}...)(?<!999)ize
Ebben az esetben az első teszt a megelőző hat karaktert nézi,
és azt vizsgálja, hogy az első három számjegy-e, ezután a
második feltétel a maradék három karaktert nézi, hogy azok
nem a "999" sorozat. A tesztek egymásba ágyazhatók bármilyen
komibinációban. Például a
(?<=(?<!ize)bigyo)figyula
arra a "figyula"-ra illeszkedik, amit egy "bigyo" előz meg,
ami előtt nem áll "ize". Miközben
(?<=\d{3}(?!999)...)ize
egy másik minta az olyan "ize"-kre, amelyek előtt három
számjegy s ezután három olyan karakter áll, amely nem "999".
A teszt-minták nem "gyűjtő" részminták, és nem ismételhetők,
hiszen nincs sok értelme ugyanazt többször tesztelni.
Ha bármilyen teszt "gyűjtő" részmintát tartalmaz, akkor
ezek a részminták is beleszámítanak a "gyűjtő" részminták
számozásába, azonban csak pozitív tesztekre lesz végrehajtva
a megtalált szövegrész "begyűjtése", mert tagadó tesztek
esetén ennek nincs értelme.
A tesztek beleszámítanak a zárójelezett részmintákra
vonatkozó 200-as felső korlátba.
A mind a maximalizáló (mohó) mind a minimalizáló (szerény)
ismétlés esetén a további részek sikertelen illesztése a
általában az ismételt elem újbóli kiértékelését eredményezi,
hogy eltérő ismétlésszámmal a minta maradéka illeszkedik-e.
Néhány esetben hasznos ezt megelőzni akár a mintaillesztés
viselkedésének megváltoztatásával, vagy hagyni, hogy az
illesztés hamarabb elbukjon - mint egyébként -, ha a minta
készítője tudja, hogy nincs értelme folytatni.
Nézzük a következő példát, ahol a \d+ize mintát a
123456bigyo
szövegre illesztjük.
Miután 6 számjeggyel végzett,az illesztés elbukik az "ize"-n.
Ekkor a szokásos lépés, hogy megpróbálja újból 5 majd 4 és
- és így tovább sorjában - eggyel kevesebb számjegyet illeszteni
a "\d+"-re , amíg végül minden lehetőséget kimerítve
az illesztés elbukik. Az egyszeri részminták azt a lehetőséget
biztosítják nekünk, hogy ha egyszer a minta egy darabja
illeszkedett, akkor az ne legyen újra és újra kiértékelve a
fenti módon, hanem az illesztés fejeződjön be azonnal, ha az
"ize"-t nem tudja illeszteni mar az első alkalommal. Ennek a
jelölésére egy speciális zárójelezés szolgál (?>)
(?>\d+)bigyo
Ez a zárójelféle lezárja a közrefogott részmintát, ha az
egyszer már illeszkedett,és az illesztés későbbi sikertelen
szakaszában megakadályozza, hogy az illesztés visszalépjen
ebbe a részbe. Emellett azonban az előző elemekre a
visszalépegetés a szokásos módon történik.
Másfajta leírása, hogy ez a fajta részminta úgy illeszkedik
a szövegre, mint ahogy egy, a pillanatnyi illesztési ponthoz
rögzített, de az eredetivel teljesen megegyező, önálló minta
lenne.
Az egyszeri részminták nem "gyűjtő" részminták. Egyszerű
esetekben egy maximalizált ismétlésnek tekinthető, amely
minden lehetőt elnyel - ahogy a fenti példában. Miközben
tehát a \d+ és a \d+? is annyi karaktert készül elnyelni,
hogy a minta maradék része is illeszkedni tudjon, addig a
(?>\d+) csakis a teljes számjegy sorozatra illeszkedik.
Ez a szerkezet egymásba ágyazható, és természetesen
tartalmazhat tetszőlegesen bonyolult részmintákat is.
Az egyszeri részminták a hátratekintő tesztekkel közösen
hatékony a szöveg végére illeszkedő mintát képesek megadni.
Nézzük a következő mintát
abcd$
egy hosszú, nem illeszkedő szövegre alkalmazva. Mivel az
illesztés balról jobbra történik, PCRE a tárgyszöveg minden
"a" betűjét végignézi, és megvizsgálja, hogy onnantól a
minta többi része illeszkedik-e. Ha a mintát így adjuk meg:
^.*abcd$
akkor a kezdő .* először a teljes szövegre illeszkedik, de
mikor a minta maradéka elbukik - hiszen nem következik
semmilyen "a" betű -, az algoritmus visszalép, hogy az
utolsó karakter kivételével mindent elnyeljen, majd az
utolsó két karakter kivételével, stb. Az "a" megkeresése
mégegyszer lefedi az egész szöveget - most jobbról balról -,
ez sem jobb. Ha azonban a mintát az alábbi alakra hozzuk
^(?>.*)(?<=abcd)
az eljárás nem tud visszalépni .* elemre, csak az egész
szövegre tud illeszkedni a minta. A soron következő
hátratekintő teszt pedig az utolsó négy karaktert ellenőrzi.
Ha a teszt sikertelen, akkor az illesztés nyomban elbukik.
Hosszú szövegek esetén ez a megközelítés jelentős - mérhető
- különbséget jelent a feldolgozási időben.
A korlátlan ismétlésű részmintákat tartalmazó mintákban,
amelyek maguk is korlátlan számban ismétlődhetnek, az
egyszeri részmintával akadályozható meg egyedül az, hogy
néhány sikertelen illesztés valóban hosszú ideig tartson. A
(\D+|<\d+>)*[!?]
minta azokra a szövegekre illeszkedik, amelyek korlátlan
számú nem számjegy karakterek vagy <> közé írt számjegyek
sorozatából és egy !-ből vagy ?-ből állnak. Ha illeszkedik,
az gyorsan kiderül. Ám ha az
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
szövegre próbáljuk illeszteni, akkor sok időt vesz igénybe,
mire "értesülünk a kudarcról". Ez azért van, mert a szöveget
nagyon sokféleképpen lehet feldarabolni két ismétlés között
és mindet végig kell próbálni. (A példában azért szerepelt
[!?] a minta végén egy egyszerű karakter helyett, mert Perl
és PCRE is rendelkezik egy beépített optimalizálással, amely
lehetővé teszi a sikertelenség korai jelzését, mert
megjegyzik az utolsó illesztendő karaktert és korán
jeleznek, ha az nincs benne a tárgyszövegben.)
Ha a mintát a következőképp módosítjuk:
((?>\D+)|<\d+>)*[!?]
akkor a nem számjegyekből álló sorozatot nem lehet széttörni
és hamar kiderül, hogy az illesztés nem sikerült.
Lehetőség van arra, hogy egy teszt (assertion) eredményétől
vagy egy előző "gyűjtő" részminta illeszkedésétől függően
más-más részmintával folytatódjon az illesztés. A feltételes
részminták két alakja:
(?(feltétel)igen-minta)
(?(feltétel)igen-minta|nem-minta)
Ha a feltétel teljesül, az "igen-minta" lesz illesztve,
egyébként a "nem-minta", ha megadtunk ilyet. Ha 2-nél több
választható részmintát adtunk meg, akkor az a kiértkelés
- fordítás során hibát okoz.
Kétfajta feltételt lehet megadni.Ha a kerek zárójelek között
csak számjegyek szerepelnek, akkor ezt egy hivatkozásként
értelmezve a feltétel abban az esetben teljesül, ha a
hivatkozott "gyűjtő" részminta előzőleg már illeszkedett a
szöveg valamely részére. Nézzük a következő mintát, amelyben
a térközök nem számítanak, csak az olvashatóságot és a
könnyebb tárgyalást szolgálják. (Feltételezzük, hogy a
PCRE_EXTENDED be van kapcsolva):
( \( )? [^()]+ (?(1) \) )
A minta első része egy nem kötelező kerek nyitó zárójelre
illeszkedik, és ha ez a karakter szerepel, akkor az első
begyűjtött - megtalált szövegrész (\1 vagy $1 numerikus
változó) ezt fogja tartlamazni. A minta második része a nem
kerek zárójelekre illeszkedik. A harmadik részben található
a feltételes részminta, ami azt teszteli, hogy az első
részben a nyitózárójel illeszkedett-e vagy sem. Ha igen,
azaz ha a tárgyszöveg nyitó zárójellel kezdődött, akkor az
"igen-részminta" érvényre jut, és a bezáró kerek zárójel már
kötelező lesz, egyébként - mivel nincs megadva "nem-minta" -
semminek nem kell illeszkednie. Magyarán ez a minta az
elhagyható zárójelek közé fogott zárójeleket nem tartalmazó
karaktersorozatra illeszkedik.
Ha a feltételrészben nem csak számjegyek vannak, akkor annak
kötelezően egy tesztnek (assertion) kell lennie. Ez lehet
akár előre- vagy hátratekintő, állító vagy tagadó felétel
is. Tekintsünk most egy, két választható mintából álló
példát, ahol a térközök szintén nem számítanak:
(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
(Az első sorban a tesztfeltétel,
a másodikban a két választható minta.)
A feltétel olyan előretekintő teszt, ami azt vizsgálja, hogy
egy betű előtt elhagyható, nem betűkből álló karaktersorozat
áll, azaz legalább egy betű jelenlétét vizsgálja. Ha ez a
betű jelen van a szövegben, akkor a tárgyszöveg az első
mintára illeszkedik, egyébként a másodikra. Ez a minta vagy a
"dd-aaa-dd" vagy a "dd-dd-dd" alakú szövegekre illeszkedik,
ahol "aaa" három betűt, "dd" pedig két számjegyet jelez.
A (?# karartersorozat megjegyzések kezdetét jelzi a mintán
belül, amely a következő bezáró kerek zárójelig tart. A
megjegyzéseket nem lehet egymásba ágyazni, és a bennük
előforduló karakterek nem játszanak semmilyen szerepet a
mintaillesztés során.
Ha a PCRE_EXTENDED módosító be van kapcsolva, akkor
karakterosztályon kívüli visszaperjel nélküli # karakter
"egy soros" megjegyzést vezet be, amely a legközelebbi újsor
karakterig tart.
Nézzük az egymásba ágyazható zárójeles kifejezésekre
illeszkedő minta problémáját. Rekurzió használata nélkül a
legtöbb, amit tehetünk, hogy rögzített számú egymásba
ágyazhatóságot kezelő mintát használunk. Nem megoldható a
tetszőleges mélységű egymásbaágyazhatóság.
Perl 5.6 kísérleti jelleggel biztosítja a lehetőséget a
reguláris kifejezések rekurzív bejárására (több más mellett).
A különleges (?R) elem jelenti a meghatározott önhivatkozási
pontot.
A PCRE minta, amely megoldja a zárójelezett szövegek
problémáját (feltéve, hogy a PCRE_EXTENDED módosító be
van kapcsolva, tehát a térközök nem részei a mintának) a
következő:
\( ( (?>[^()]+) | (?R) )* \)
Először egy nyitó zárójelre illeszkedik, ezután tetszőleges
hosszúságú karakterresorozatra, amely vagy nem tartalmaz
zárójeleket, vagy rekurzívan az egész mintára illeszkedik (a
zárójelezett szövegekre). Végül a bezáró zárójel következik.
Ez a sajátságos minta korlátlan számú, egymásba ágyazott
ismétlést takar, ezért a zárójel nélküli szövegrészre
illesztésnél az egyszeri részminta használata nagyon fontos,
kiváltképp ha nem illeszkedő tárgyszövegre alkalmazzuk. Ha
például a
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
szövegre próbáljuk a mintát, akkor nagyon hamar megkapjuk az
eredményt. Ha nem használnánk az egyszeri részmintát, akkor
az illesztés nagyon sokáig tartana, mert rengeteg különböző
módon lehet a tárgyszöveget felszeletelni a * és + kvantorok
(sokszorozók) között, és minden lehetőséget ki kell
próbálni, mire az illesztést végleg sikertelennek lehet
minősíteni.
A "gyűjtő" részminták által begyűjtött szövegek a rekurzió
során a legutoljára illesztett szövegrészek.A fenti mintát a
(ab(cd)ef)
szövegre alkalmazva a "begyűjtött" / megtalált rész az "ef"
lesz, amely a felső szinten az utolsó felvett érték. Ha
további zárójeleket helyezünk el a mintában ekképpen:
\( ( ( (?>[^()]+) | (?R) )* ) \)
^ ^
^ ^
, akkor a "ab(cd)ef" szöveg lesz legkülső "gyűjtő" zárójel
értéke. Ha 15-nél több "gyűjtő" zárójel van a mintában,
akkor PCRE tartalék memóriát foglal le, hogy az adatokat itt
tárolja a rekurzió alatt (pcre_malloc-kal foglalja le, és a
pcre_free-vel szabadítja fel azután.) Ha nem lehet több
memóriához hozzájutni, akkor csak az első 15 "gyűjtő"
zárójelnek menti el az adatait, minthogy lehetetlen "nincs
elég memória" hibaüzenetet kiadni a rekurzión belül.
Bizonyos minták sokkal hatékonyabbak, mint mások, például
[aáeéiíoóöőuúüű] karakterosztály hatékonyabb, mint ugyanezt
választható mintákkal (a|á|e|é|i|í|o|ó|ö|ő|u|ú|ü|ű) megoldani.
Általában a legegyszerűbb szerkezet, amely a kívánt viselkedést
biztosítja rendszerint a leghatékonyabb. Jeffrey Friedl könyve
rengeteg példát tartalmaz, hogyan kell reguláris kifejezéseket
optimalizálni a hatékony végrehajtáshoz.
Ha a minta .* -gal kezdődik, és a PCRE_DOTALL módosító
be van kapcsolva, akkor PCRE a mintát hallagtólagosan
"rögzíti", mivel az csak a tárgyszöveg elejére illeszkedhet.
Ha ez a módosító nincs beállítva, akkor nem élhet ilyen
optimalizálással, mivel a . metakarakter nem illeszkedik az
újsorkarakterre, ezért előfordulhat, hogy a mintát minden
egyes újsortól illeszteni kell, nem csak a szöveg elejére. A
(.*) második
minta úgy illeszkedik az "első\nés második" szövegre (ahol a
\n az újsort testesíti meg), hogy az első "begyűjtött"
szövegrész az "és" lesz. Ehhez a PCRE-nek minden újsor után
újból meg kell próbálni az illesztést.
Ha az ilyesfajta mintákat olyan szövegekre alkalmazod,
amelyekben nincsenek sortörések (újsorkarakterek), akkor a
legjobb teljesítmény a PCRE_DOTALL módosító beállításával
vagy a "rögzítés" egyértelmű megadásával lehetséges: ^.*.
Ez megkíméli a PCRE-t, hogy végignézze a tárgyszöveget
újsorkaraktert keresve, ahonnan az illesztést újrakezdheti.
Vigyázz azokkal a mintákkal, amelyek egymásba ágyazott
határozatlan számú ismétlést tartalmaznak. Ezek a minták sok
időt vesznek el, ha nem illeszkedő szövegre kell alkalmazni
őket. Nézzük a
(a+)*
mintát! Ez 33 féleképpen illeszkedik az "aaaa" szövegre, és
ez a szám rohamosan növekszik, ahogy a szöveg egyre hosszabb
lesz. (A * illeszkedhet 0-szor, 1-szer, 2-szer, 3-szor vagy
4-szer, és - 0-t kivéve - minden esetben a + is különböző
számúszor.) Amikor a minta fennmaradó része ilyen és az
illesztés egésze sikertelenül érne vége, PCRE elvben
végigpróbálja az összes lehetőséget, ami rendkívül sok időt
vehet igénybe.
Néhány egyszerűbb minta esetén optimalizálás történik, mint
például
(a+)*b
, ahol literális (önmagára illeszkedő) karakter követi a
vizsgált részt. Mielőtt a hagyományos illesztési eljárás
elkezdődik, PCRE megvizsgálja, hogy előfordul-e később a
mintában "b", és ha nem, akkor azonnal sikertelennek
minősíti az illesztést. Amikor azonban nem literális követi
a mintarészt, akkor ez az optimalizáció nem használható.
A különbséget megvizsgálhatod a
(a+)*\d
minta viselkedésével összehasonlítva. Az előbbi szinte
azonnal véget ér, ha csupa "a"-ból álló sorozatra illesztik,
míg az utóbbi kipróbálása jelentős időt vesz el 20
karakternél hosszabb tárgyszövegekre.