ࡱ> {`4zbjbjFF ;,,|v T)8lV<3/ 6664я ]dddddd$h7ra g" 661QQQ 66Q QQ66 ;,;0/gLX, Hݏa^QL ݏݏݏ;ݏݏݏ/ 333TnD333n r   Regulris kifejezsek Szvegfeldolgozs elmlet s gyakorlat regexekkel A szvegekben keress, egyes rszek cserje, kiemelse mr az informatika kezdete ta foglalkoztatja a szakembereket. A regexek segtsgvel rendkvl kifejezQ mdon tudunk rszleteket megfogni egy hosszabb s nem szigoran szablyos szvegbQl is. Ennek elmleti s gyakorlati krdseit boncolgatjuk a kvetkezQ kilenc oldalban. Regex trtnelem Regulris kifejezs, angolul Regular Expression. Eredetileg a neuronfiziolgiban vezettk be ezt a fogalmat az 1940-es vekben. redekes nem, hisz akkor hol voltak mg a maihoz hasonl szmtgpek? Aztn jpr vvel ksQbb Stephen Kleene kitallta a Regulris Halmazokat mint matematikai elmletet, s ehhez vezetett be egy jellsmdot, amit Regular Expression-nek hvott. Akit rdekelnek a matematikai rszletek (engem nem), annak itt a referencia: Robert L. Constable, "The Role of Finite Automata in the Development of Modern Computing Theory," in The Kleene Symposium, eds. Barwise, Keisler, and Kunen (North-Holland Publishing Company, 1980). A regexek elsQ gyakorlati felhasznlsa Ken Thompson nevhez fqzQdik (remlem nem kell bemutatnom, ha igen, akkor srgQsen do google!), aki  Regular Expression Search Algorithm cmq cikkben vezeti be a regulris kifejezsek hasznlatt szvegfeldolgozsra. P rta meg a qed nevq szvegszerkesztQt, ami a Unixon jl ismert ed kifejlQdshez vezetett. Ezekben a szvegszerkesztQkben mr volt regex kirtkelQ, gy lehetQv vlt bonyolultabb szvegrszek megtallsa s cserje is. Az ednek volt egy parancssori eszkze, ami szvegfjlok soraira egyezQ regulris kifejezseket nyomtatott ki. Ez volt a "Global Regular Expression Print , rvidtve grep. Bzom benne, hogy nem Unixon felnQtt programozk is hallottak errQl a programrl. Ezek a kezdeti programok persze mg sokkal egyszerqbb regulris kifejezseket ismertek, mint a mai rtelmezQk, de (mint minden fejlQds ebben a szakmban) a regexek is iteratv mdon fejlQdtek. Ezutn jtt a jval tbb metakaraktert hasznl egrep, ami mr teljesen ms elven mqkdtt, mint elQdje. A grep Deterministic Finite Automat-ot (DFA) hasznlt, mg az egrep Nondeterministic Finite Automat-ot (NFA). Egyszerqen megfogalmazva a DFA gyors, de butbb, az NFA egyes esetekben rettentQ lass, de sokkalta okosabb, s szabadsgot ad a regexeken keresztl a motor kzvetlenebb vezrlsre. A mai regex motorok zme NFA. Majd jtt a sed, az awk, a lex, amelyek mind valamilyen szempontbl tovbbfejlesztettk a regexek nyelvtant. A sokfle nyelvjrs kztt a POSIX szabvny prblt rendet rakni. LegfQbb elQnye, hogy bevezette a locale fogalmt, gy a betq vgre nem csak az angol ABC karaktereit jelentette. Mi magyarok ismerjk a szakmban az  angol diszkriminct , gy rlnk a Posix trekvseinek. Napjainkban a Perl az a krnyezet, amely a regulris kifejezsek hasznlatban s jtsokban a fQ hzerQ. A pldkban a .NET Framework regex osztlyait hasznljuk, amelyeket a Perl 5 regexei alapjn modelleztek, gy nagyon magasszintq regex tmogatst kapunk. Bevezets A regex a regulris kifejezs rvidtse. A cikknkben trgyalt szvegeket bogarsz regexek mr szokszor nem regulrisak matematikai rtelemben, ezrt ltalban egyszerqen regexknt hivatkozunk rjuk, megklnztetve Qket a matematikai regulris kifejezsektQl. Nos, mi is az a regex? Egy olyan ler nyelv, amely segtsgvel szvegek klnbzQ rszeit ragadhatjuk meg, rhatjuk le. Gondoljunk a fjlrendszerre: dir a.txt Ez kilistzza az a.txt fjlt. Mi van, ha az sszes szvegfjl kell? dir *.txt Bevezettnk egy metakaraktert, a *-ot (csillagot), amit gy definiltunk, hogy egyezik brmilyen fjlnvre. Nos, a regexek hasonlak, csak sokkal tbb metakarakter tallhat bennk, gy sokkal gazdagabban fogalmazhatjuk meg az illesztendQ szveget. Kiindul pldnk a kvetkezQ lesz. Szeretnnk egy szvegben megkeresni a dadogsokat dadogsokat. Gyakori szvegszerkesztsi hiba az ismtls, ezt kellene megkeresni egy tetszQleges szvegben. Azt gondolnnk, minek ide regex, sima sztringkezelQ eszkzkkel is megoldhat a problma. Pldul feldarabolhatnnk a szveget szavakra (whitespace-ek mentn), majd vgigmenve a listn sszehasonltjuk az egyms utn kvetkezQ szavakat. Ha egyeznek, ismtlst talltunk. Igen m de lehet, hogy a szavakat markup tagok hatroljk, mint pl. egy html szvegben: Ez is <i>dadogsnak</i> <u>Dadogsnak</u> szmt. Ebben az esetben is meg kell tallni az ismtlQdQ szavakat. Termsztesen ez s minden ms problma is megoldhat alapvetQ sztringmqveletekkel (Find, Split, Replace), de sokszor egy regexes megolds sokkal egyszerqbb lesz. A problmt megold regex gy nz ki: (\b(\w+)(\s|<[^<>]+>)+(\1)\b( A regex csak a nyilak kztti rsz, de a nyilakat mindig kirom mind a szvegekben mind a kdblokkban, hogy jelezzem ha regexrQl beszlnk. A cikk clja, hogy a vgre mindenki szmra magtl rtetQdQ legyen ez a regex. Karakteregyezsek Egy karakter sajt magval mutat egyezst, ha nem vezrlQkarakter. A pldkban az egyezseket mindig alhzssal jellm. Ahol fontos, ott kirom, hny egyezst tallna a regex motor. (e( Mesterkurzus  2 egyezs A legtbb regex motor tkapcsolhat kis-negybetqre nem rzkeny mdra, ilyenkor rtelemszerqen alakulnak az egyezsek. .NET-ben ez a RegexOption.IgnoreCase opcival rhetQ el. (e( Embergyerek  4 egyezs Karakterhalmaz egyezsek Egy karakterhalmaz egyezst mutat ugyanazzal a karakterhalmazzal, szhatrtl fggetlenl. (ek( Mekk Elek legyek 3 egyezs A regexekben minden karakter szmt, mg a whitespacek is. (1492. ( Szletett: 1492. 08. 12. 1 egyezs de (1492. ( Szletett: 1492.08.12. 0 egyezs Ez fontos, mert sokszor hajlamosak vagyunk egy bonyolultabb regexet picit szellQsebb tenni szkzkkel, m ettQl megvltozik a regex viselkedse. Egyes regex implementcikban, mint a Perl vagy a .NET, lehetQsg van whitespace-ek s kommentek hasznlatra a regexekben. .NET-ben a RegexOptions.IgnorePatternWhitespace opci utn a whitespace-ek nem szmtanak a patternben, s # utn mg megjegyzseket is lehet fqzni a sorokhoz. De akkor ebben az esetben hogyan rjuk le a whitespace-eket? Hasonlan, mint a legtbb stringet feldolgoz programnyelven: escape szekvencikkal. A kvetkezQ tblzatban megtekinthetjk a legfontosabb (de nem az sszes) helyettestQ karaktert. Karakter LersKznsges karakterekMind, kivve . $ ^ { [ ( | ) * + ? \\bVisszatrls (backspace) \u0008 ha [] karakterosztlyban van, egybknt szhatr (ezekrQl bQvebben kicsit ksQbb)\tTab \u0009.\rKocsivissza \u000D.\njsor karakter \u000A.\x20Egy ASCII karakter hexa kddal, pontosan kt digiten lerva. Ez pl. egy szkz.\cCASCII vezrlQkarakter (32-nl kisebb kd karakter), ez pl. a CTRL-C\u0170Egy Unicode karakter, pontosan ngy hexa szmjeggyel lerva, ez egy nagy P betq\Ha nem escape-elt karakter elQtt van, akkor egyszerqen elhagysra kerl, gy marad a mgtte levQ karakter. Pl. \g egyszerqen egy g betq. A \uxxxx hexa szm a karakter n. code pointja az unicode tblzatban, nevezzk egyszerqen karakterkdnak. Lthat, hogy ezt a jellst nyugodtan lehet hasznlni regexekben, gy biztos nem frdnk be a sunyiban o betqv tkonvertldott Q betqkkel (a szvegszerkesztQk miatt). A kdokat legegyszerqbben a Windows Character Map-ban tallhatjuk meg. A visszafele perjel (\) bershoz duplzni kell (\\). Karakterosztlyok Eddig csak konkrt karakteregyezseket vizsgltunk meg. Az f betq az f-fel egyezik, ksz. Termszetesen lehet hasznlni olyan konstrukcikat, amelyek tbb mint egyfle karakterrel egyeznek, ezek a karakterosztlyok. Karakterosztlyokat ([...]( (szgletes zrjelek) kztt lehet definilni. Az osztlyban felsorolt brmelyik karakter szerepelhet az egyezsben, de nagyon fontos, hogy pontosan egyetlen karaktert helyettest egy karakterosztly kifejezs, nem tbbet. ([rsk]( Mesterkurzus 5 egyezs Lthat, hogy a ([rsk]( jelentse: egy karakter, ami r vagy s vagy k lehet. ([0123456789]( Szletett: 1492. 08. 12. 8 egyezs A ([0123456789]( brmilyen decimlis szmjegyre illeszkedik, ezrt 8 ponton egyezik a msodik sor tesztszvegvel. Karaktertartomnyokat is megadhatunk karakterosztlyokban - (mnusz)-szal elvlasztva, gy nem kell felsorolni minden egyes karaktert. Ez a plda egzaktul azonos az elQzQvel, csak rvidebb: ([0-9]( Szletett: 1492. 08. 12.  8 egyezs A kvetkezQ regexet gy kell rtelmezni: brhol a szvegben egy decimlis szmjegy, amit egy decimlis szmjegy kvet. Lehet, hogy gy tl analitikusan hangzik, de bonyolultabb regexeknl a tl intuitv, beleltom n mit csinl egyszuszra gondolkodsmd gyakran tvtra csal. ([0-9][0-9]( Szletett: 1492. 08. 12. 4 egyezs! Karakterosztlyon kvl a - jel kznsges karakter: ([0-9][0-9]-( Szletett: 1492-08-12. 2 egyezs! rdemes odafigyelni, hogy sok karakter mskpp viselkedik karakterosztlyon kvl s bell. De ez mg nem minden! A - jel karakterosztly elejn s vgn kznsges karakter. Nzzk kontrasztba lltva. Ebben a pldban a regex a a-tl z-ig terjedQ karaktert tartomny jelli ki: ([a-z]( c - d  2 egyezs Itt viszont az elsQ mnusz kznsges karakter: ([-a-z]( c - d  3 egyezs Karakterosztlyon bell az utols pozcin is kznsges karakter lenne, gy az ([a-z-]( azonos a fenti regexel. Egy karakterosztlyban tbb tartomny s karakter is felsorolhat vegyesen is. Pldul: ([eza0-2]( Szletett: 1975-01-10  8 egyezs (0x[0-9abcdefABCDEF][0-9abcdefABCDEF]( 0x15, 0xaF, 0x5H, 0x1B, hexa szmok  3 egyezs Gyakran egyszerqbb megfogalmazni gy egy karakterhalmazt, hogy brmilyen karakter, kivve ezt s ezt. Erre val a neglt karakterosztly. A jellsmdja egy ^ (kalap) a karakterosztlyt jellQ [ (nyit szgletes zrjel) utn kzvetlenl. A kvetkezQ plda jelentse: brmilyen karakter, kivve a 0-9-ig terjedQ tartomnyt, magyarul brmi, ami nem szm: ([^0-9]( Szletett: 1492. 08. 12.  16 egyezs Nem elsQ pozcin mr kznsges karakter a ^: ([0-9^e]( Sz^letett: 1492. 08.^ 12.  12 egyezs ElQre definilt karakterosztlyok Vannak gyakori esetek, amelyeket nem fontos hosszan karakterosztlyknt definilni, hanem vannak elQre elksztett rvidtsek rjuk. Gyakran kell a ([0-9]( karakterosztlyt hasznlni, amit a (\d( helyettesthet. A kvetkezQ plda ngy egyms utni szmjegyre ad egyezst. Figyelem! Nem ngydigites szmokat keres! Mint mr tudjuk, az egyezsek fggetlenek a htkznapi rtelemben vett szhatrtl, gy az elsQ hossz szmban hrom egyezs is lesz, a hrom egymst kvetQ ngy szmjegybQl ll blokk: (\d\d\d\d( 1258632455458: 1492. 08. 12. 4 egyezs A \D a ([^0-9]( karakterosztllyal egyezik meg, azaz nem szmjegy. (\D\D\D\D( Szletett volna: 1492. 08. 12. 4 egyezs Az egyezsek kifejtve: 0 => Szl 1 => etet 2 => t vo 3 => lna: Sajnos az alhzsos jellsmd idQnknt nem egyrtelmq, ezrt nha kifejtem a kimenetet. Amikor progamozzuk a regexeket, ebbQl nincs gond, mert a tallatokat egy kollekciban kapjuk vissza. A (\w( brmilyen betqt, szmot vagy alhzsjelet (_) jelent. Nem brmilyen karaktert, hanem brmilyen betqt, belertve a gonosz Qq betqket is. Pontosabban: ez attl fgg. A .NET-es implementci alapban minden betqt belert, de tkapcsolhat ECMA mdba is (RegexOptions.ECMAScript), ahol a (\w( == ([a-zA-Z0-9_](. Azaz ettQl kezdve csak az angol ABC betqivel foglalkozik, gy az kezetes betqinket mind kihagyn. Figyelem! Ms implementciban lehet, hogy eleve gy mqkdik a regex motor, azrt les bevets elQtt mindenkppen tesztelni kell kezetes betqkkel is az egyezseket! Norml mdban: (\w\w\w( Szletett: 1492. 08. 12. 0 => Sz 1 => let 2 => ett 3 => 149 RegexOptions.ECMAScript esetn lthat, hogy az betq nem tartozik bele a (\w(-be, gy az elsQ hrmas betqcsoportot csak a  let -nl tallja meg a motor: (\w\w\w( Szletett: 1492. 08. 12. 0 => let 1 => ett 2 => 149 Mi a helyzet az euro ( ) karakterrel? Az betq? Egyltaln, hol tallhat ez a billentyqzeten? Nos, elsQ krben n sem talltam. Aztn rkerestem az euro-ra az unicode.org-on [1], ahol talltam egy riportot [2], mely szerint az euro karakter a 2.1-es unicode szabvnyban jelent meg. Most egybknt (2003. oktber) a 4.0 unicode szabvny az aktulis. Nos, az euro a 20AC hexa kdot kapta. Szp, mi? Hol vannak mr az ASCII 7 s 8 bites szmokkal brzolt betqk! Kitartbbak a Character Map-ban is megtallhatjk, legalbbis XP+SP1-en biztos:  Euro szimblum a Windows XP Character Map-ben Nos, a krds ugye az, hogy a (\w(-be beletartozik-e az euro? Rvid teszttel kiderl, hogy nem. Az euro szimblum kategrij karakter, nem betq. A .NET regex motor nagyfok unicode tmogatst ad, gy a karakterek osztlyozsnl is az unicode szabvny ltal meghatrozott kategrikat hasznlja [3]. Olyannyira, hogy ezt mg ki is vezettk neknk. A (\p{Kategrianv}( kifejezssel hivatkozhatunk a megfelelQ kategriba tartoz karakterekre. A kategrik nevt a [3] tblzat tartalmazza. Nzznk nhny rdekes pldt! (\p{Ll}( #Letter, lowercase, azaz kisbetq Szletett A Nagybetq $ % ^ .+ (\p{Lu}( #Letter, uppercase, azaz nagybetq Szletett A Nagybetq $ % ^ .+ (\p{No}( #Number, other, azaz egyb szm Szletett A Nagybetq 45 $ % ^ .+ (\p{Ps}( #Punctuation, open, azaz nyit rsjel (alma) [krte] {szilva} (\p{Po}( #Punctuation, other, egyb rsjel $ % ^ .+ - _ "Idzet.", 'ez is!' (\p{Sc}( #Symbol, currency, pnz szimblum $ % ^ . + - _ / * ^ ~ Ft Csak meglett az eur, a pnz szimblumok kztt talljuk! A msodik alkategria karaktert el lehet hagyni, gy a (\p{L}( az sszes betqt jelenti, amiben nincsenek benne a szmok s az alhzsjel, azaz nem ugyanaz, mint a (\w(. Egybknt a furcsa karakterek megkeresshez hasznos lehet a Character Map Advanced nzete, amikor Unicode kategrik szerint szqrve lthatjuk a karaktereket.  Csak a pnzeket reprezentl karakterek A (\W( (nagy W) minden nem betqt jell, azaz (^\w(. A (\s( brmilyen whitespace karaktert jelent. A whitespace-eket is az Unicode szabvny rgzti, de leegyszerqstve a szkz, tabultor, kocsivissza s a soremels tartozik bele. Vannak mg extra karakterek is (pl. fggQleges tabultor), de ezek ltalban nem rdekesek szmunkra. A pontos lista gy nz ki: ([\f\n\r\t\v\x85\p{Z}]( A Z unicode kategria a szepartor karaktereket jelli, a 85 hexa kd karakter pedig a szkz nem PC-s rendszerekben (bizarr). (\s( alma, majd egy tab: s ms A (\S( (nagy S) minden nem whitespace-t jell, azaz (^\s(. Az univerzlis dzsker: a pont A (.( (pont) brmilyen karakterrel egyezik kivve az jsor (\n) karaktert. Ha RegexOptions.Singleline mdban vagyunk, akkor az jsorral is. (.t.( Szletett ma 2 egyezs 0 => ete 1 => tt(space) (.....( Szletettma 3 egyezs 0 => Szle 1 => tett< 2 => i>ma< Norml md viselkeds (a \r\n a kocsivissza-soremels pros, amik nem ltszannak): (.......( #7 db karakter ElsQ sor(\r\n) Msodik sor(\r\n) Lthat, hogy az elsQ sorban mr nem volt msik 7 egybefggQ karakterhalmaz, gy csak egy egyezst tapasztalunk. A msodik sorban gyszintn. Ezzel szemben RegexOptions.Singleline mdban a sorvgi jsor (\n) karakter nem lltja meg a motort, gy a sorokon tvelve is egyezst tall a (.......(: ElsQ sor(\r\n) Msodik sor(\r\n) 0 => ElsQ so 1 => r(\r\n)Mso 2 => dik sor A msodik egyezsben benne van az elsQ sor  r betqje, a  kocsivissza-soremels pros s a  Mso karakterek. A pontot nagyon gyakran fogjuk arra hasznlni, hogy ismeretlen szvegre lltsunk fel egyezseket. A kvetkezQkben sok pldt fogunk ltni a hasznlatra. Pozcionlis karkterek (Anchors vagy Atomic Zero-Width Assertions) Az eddig ltott karakterosztlyok, jokerek mindig helyet fogaltak el, azaz miutn a regex motor egyezst tallt, tovbblp egy karakterpozcival mind a forrsszvegben mind a regexben, s onnan keres a regex maradkra egyezst. Pldul a (.t.( esetn (tesztsztring: Szletett ma) az elsQ (.( tall egy karaktert, az  S -t, majd a motor tovbblp a regexben a (t(-re, s megnzi, hogy az illeszkedik-e a sorok kvetkezQ karakterre, a  z -re. Mivel nem, eldobja ezt a prblkozst, s tovbblp a forrsszvegben a  z -re, visszatekeri a regexet az elejre, s nekill a (.(-ot jra rilleszteni az karakterre, stb. Azaz a lnyeg, hogy a norml karakter vagy karakterosztly egyezsek helyet foglalnak el, tovbblptetik a forrsszveget. Ezzel szemben a pozcionlis karakterek nem foglalnak el helyet, csak kijellnek egy pozcit a forrsszvegben, aminek teljeslni kell ahhoz, hogy egyezst kapjunk. A (^( (kalap) a szveg vagy sor elejt jelenti. Alapban szveg elejt, RegexOptions.Multiline esetn a sor elejt. Azaz a multiline zemmdban a regex motor soronknt dolgozza fel a szveget, hasonlan a grep-hez. (A norml eset a sed mqkdshez hasonl.) Norml md: (^..( ElsQ sor(\r\n) Msodik sor(\r\n) Multiline md: (^..( ElsQ sor(\r\n) Msodik sor(\r\n) A ($( (dollr) a szveg vagy sor vgt jelenti. A multiline ugyangy hat r, mint a (^(-ra. (ma$( alma alma A msodik plda csak azokra a sorokra mutat egyezst, amelyekben pontosan s csakis az alma sz szerepel: (^alma$( alma almama A (^( minden sorra egyezst mutat (multiline mdban), azaz nem tl praktikus regex. Habr, ha ezzel a kifejezssel sztszednk darabjaira egy szveget, sorokra bontva kapjuk vissza. Mondjuk ennl egy String.Split egy cseppet gyorsabb lenne, de ezt azrt mg lehet tovbb alaktani, pldul .0T 0 2 j l t  <   , . 0 2 R $ *  4 D F !45@żżżųųμ|x|tphtihxh_hkh'Mhy}h7h6ehhj\h-Nh h65 h5hh{)CJhh#CJhh'MCJhh&|CJhhGCJ h{)h{)hhhh{)CJ4aJ4hhCJ4aJ4h,00 T 52!"gd)`gd$#Tgdk@&gdlgdgd[$gdgdx(z2z  RTr " rZ\l.02@N.ѵh,nh~mH sH h4h~hBWhPhDhw*h&ht\hI<hGh$Nho0h$#Th@[h64-hE4h~/hRh6hYAh: v hlhlh(ShlhGhtih'M3.:<JLNR^lnNf:@d  !"¾{hah_2h)`h"5 hV5 h {5 h05hVhj h9dh]h=Rthsp`h*h.hsh<h9hI<heJh8h0hDh"h?hx|h~h,nh~mH sH h,nhx|mH sH 0""""#######%%&&<&>&T&X&'2'4'''))) ****0*8*H*J*L**+f+,,V,X,Ͽϻ~~~m! jh Eh E\mHnHsHhRhM#h` hM#h4CmHnHsHhM#hM#\mHnHsHhM#hM#\mHnHsHhGh4ChhhFE>*hhFE6hFEh^Hhaha6hGhYKhahamHnHsHhah@!h.X)""######%'4)))J*L*,T,V,,,N.P.t./// 0gdl@&gd"n(gd E@&gdlgdaX,,,,,---"-,-0-4-6-:-D-H-L---L.N.P.r.t..../0/>/h///////////ظn! jhlhl\mHnHsHh { hlh"h8h:huh hrh:h"n(hl hlhl hlhLh"n(hL5h}h}2h.XhMh@huhn&!h` hR! jh Eh E\mHnHsHh Eh E\mHnHsH(///////0 0"0000$1X11111111111111111tddddVhlh\mHnHsHh h >*\mHnHsH! jh h \mHnHsHh h \mHnHsH! jh h \mHnHsHhC'Ih9h^J h*hC'I hC'I^J h:^J h9h^J hl^Jh {hlhl>*\mHnHsH! jhlhl\mHnHsHhlhl\mHnHsH 0"0111111S2T2Y2v2w2222222223348gdSWVgdcgd gdp@&gdi@&gd(MgdY]gd 111111111 2)2Q2R2S2T2U2W2X2Z2\2`2b2g2i2l2m2u2˿tdddVKVhp\mHnHsHhlhp\mHnHsHhphp>*\mHnHsH! jhphp\mHnHsHhphp\mHnHsH! jhphp\mHnHsH hK(^J hwA^J h:^Jhihi^J hlh(M h(M5h"n(h(M5 hl^Jh(Mh9hmHnHsHhlh\mHnHsHh\mHnHsHu2v2w222222222222222222222222233}w}l^M^Ih(M! jhSWVhSWV\mHnHsHhSWVhSWV\mHnHsH jhSWVhSWV\ h(M^J h ^J hT h4h h \h h >*\mHnHsH! jh h \mHnHsHh h \mHnHsH! jh h \mHnHsH h4^J hP^JhT hT ^J hT ^J hi^JhphwAmHnHsH334444585:5<55555"6.666677|7(8|88888889999<9>9X99zzf_z_z hh_&hh5CJOJQJ\mH sH  hh hh~kh@h]}hHuah4hhDh^a-h2hLhOJQJ^Jh hh hhE hE^J hm^J h:^Jhh^J h^J h<^J h}^J h]}^J hK(^J%88999>99kkd$$If04&j0&a $Ifgd999v: $Ifgdkkd$$If04&j0&a99999992:t:v:x:~::::::::::::;D;F;~;;;;;<:<<<><D<J<L<<<<<<==>> >亳䥞䏈z hh: hha) hhKy hh,hKymH sH  hhN# hhk_ hh{ hh> hhN`$ hhS, hh08 hh`E hh hh9shhmH sH  hhCJOJQJmH sH /v:x:~:: $Ifgdkkd($$If04&j0&a:::: $Ifgdkkd$$If04&j0&a:::: $IfgdkkdP$$If04&j0&a::;; $Ifgdkkd$$If04&j0&a;;;<< $Ifgdkkdx$$If04&j0&a<<><L<< $Ifgdkkd $$If04&j0&a<<<> $Ifgdkkd$$If04&j0&a> > >@2A4AXABCCCCCCyttgd@&gdxgdS5$dd7$8$H$a$gdkkd4$$If04&j0&a > >>???????2@4@@@ A$A.A0A2A4AXAAABOBSBBBBBBBBBBBBC5C=CqC~CCC|xq h_h#|hhh_6h_ h_h_h~ h<h< jhT\7h&hT\7 jhT\7h<hyh`h`6h`h:hxhxhx5h&rh@h~hTsdh[hK}Chxh*hrh08hS5+CCCCCCCCCCCCCCCCCCCCCCCCCCD D DDDDǷǷǷǷdzoaaQaQahuPhuP>*\mHnHsHhuPhuP\mHnHsH! jhuPhuP\mHnHsHhuPhuP\! jhuPhuP\mHnHsHh&r jhw jhwhwhOhhh>*\mHnHsHhh\mHnHsH! jhh\mHnHsHhh\! jhh\mHnHsHCCC#D$DDEHFJFZFFFiHjHwHHHHHHIIyInJpJJJgdSGgdagdgd &gduPgdS5DD"D#D&D'D3D4DODoDDDDDDDDEEEE)EFHFJFLFNFPFRFTFVFXFZF^Fצ~p~_pWhuPh &\! jh &h &\mHnHsHh &h &\mHnHsHh &\mHnHsHh &h &\! jh &h &\mHnHsHh1hhNh:hG hP(bhP(bhP(bhh jh Z jh Zh Z hwhwhuPhuP\mHnHsHhuPhuP>*\mHnHsH!^FpFxF|FFFFFFFGG,H-H7HBHiHjHkHlHoHuHvHwHyHHHHHHHHHHHHHHֵ}mmmihahh>*\mHnHsH!hR]h6>*\mHnHsH! jhh\mHnHsHhh\mHnHsHhh\! jhh\mHnHsHhh hP`hQh & hwh &huPh &>*\mHnHsHhuPh &\mHnHsH%HHHHHHHHHHHHHHHIIIIIbIxIyIIIlJnJpJrJ|Jط捉}yuq}y`ShSGhSGmHnHsH! jhahSG\mHnHsHhLhSGh hBhhhFhR]h/ha6>*\!h/ha6>*\mHnHsHhaha>*\haha>*\mHnHsH! jhaha\mHnHsHhaha\mHnHsHhaha\! jhaha\mHnHsH|J~JJJJJJJJJJJJJK KKKKKK K"K$K*K,K*mHnHsHhLmHnHsH! jhahG\mHnHsHhuhumHnHsH! jhahG\mHnHsHhahuhLh hah:\hah:\mHnHsHhSGhSGmHnHsHhJhSG>*mHnHsHh mHnHsH! jhahSG\mHnHsHJJKKK>K@K"LLLL.M|MMMPPPQQdQfQzQQQRS@&gd~gdQ3^gd&gdcgd gdS5K@KKKKKKKK L"LLLLLLLLLLLLLMM MMMM,M.M0MxMzM|MMMMòxmb jhchc\ jhchc\hT,\mHnHsHhchc>*\mHnHsH! jhchc\mHnHsHhchc\mHnHsH! jhchc\mHnHsHhT, h h jh hN h h jh h hShhGhumHnHsH&MMMMMMMMMNNNNNOO8ONOPOOPP`PbPPPPPPPPPPӸxjxYj! jh&h&\mHnHsHh&h&\mHnHsHh&h&\! jh&h&\mHnHsHhh&hd h]h]h]h:h Rmh6h hchcmHnHsHhh:\mHnHsHhah:\mHnHsHhchc>*\mHnHsHhchc\mHnHsH PPPPPPPPPPPPQQQ`QbQdQfQhQvQxQzQQQQQQQQQQQįrbbRh5hQ3^>*\mHnHsHhQ3^hQ3^>*\mHnHsHh5h5>*\mHnHsHhQ3^hQ3^\mHnHsH! jhQ3^hQ3^\mHnHsHh5hQ3^\mHnHsH! jhQ3^hQ3^\mHnHsHh&hP hPhPhzw h]h]h&h&\h&h&\mHnHsHh&h&>*\mHnHsH QQQQQQQQQQQRSSS@SHSJSbSdSvSSSSSST2TTTTTTUUUUyuuqumimeh.h:h @hHah.7 jh.ah.a jh.ahdh jhz hzhz jhzhzh>hzj#h~h>5hFh5hPmHnHsHh5\mHnHsHh5h5>*\h5hQ3^\mHnHsHh5hQ3^>*\mHnHsH%SUU V4V5VyVzVVVVVVVVVVVbY\]^ ^^N^`^gdDsgd}gd=<*gd~|ggdgdo gdS5UVV V VVVVVVV'V*V+V,V3V4V5V7V:VV?VCVDVFVxVxtpipbp[TMpIhU jhml hzhml hHahml jhml hmlhmlhmlhzj#h.7ho mHnHsHho ho >*\mHnHsHh.7\mHnHsH!hauRh.76>*\mHnHsHh.7h.7>*\mHnHsHho ho \mHnHsH! jho ho \mHnHsHh.7ho \mHnHsH! jho ho \mHnHsHxVyVzV{V|V}V~VVVVVVVVVVVVVVVVVVVVVVVVVVVVXXεΥ΍{tptptpti{c] h\P^J hZPb^J h~|gh90h~|g h~|gh~|g hE^J h~|g^J h&$^J hh!h"h6>*\mHnHsHhh>*\mHnHsH! jhh\mHnHsHhh\hh\mHnHsHhHah\mHnHsH jhh\hF hmlh$#XX`YbYfYhYlYnYYYYYYZZZZZZZf[~[[[[[[[[[[[[[[[[\\6]h]r]t]ɾ~wssoskhhXcGh;7 jhs heo^J hs^J jhs jh S jhhs hshshQh:hph7(hwh5a h heoheohv jh5ah5ah5a^J jh5a h5a^J h90^J h\P^J h:^J*t]]]] ^ ^^^^.^2^8^J^N^`^b^r^t^^^^^^^^^^^^0_2_6_8___ǹ~w~wqkqdq]qW h"^J jh0} jh0} hec^J h ^J hsh h jhCh"U h90^JhDs h}hDsh}\mHnHsHh}h}>*\mHnHsHh}h}\mHnHsH! jh}h}\mHnHsHhec\mHnHsH! jh}h}\mHnHsHh2>h:h;7"`^r^^^^___`(`:`L`N`ccDdEdGdudvdhiTiii:jgdgdDs__________````(`*`:`<`L`N`z`|`` a0aaaaaۼ۬ېypyjd^TNH hqJ^J hE^Jh:hrW'5^J hrW'^J hZ^J ha]v^Jh{CUh{CU^J h{CU^J hm4^J h}hd>hVhd>\mHnHsH!h!yhd>6>*\mHnHsHh}hd>>*\mHnHsHhVhd>\mHnHsH! jh}hd>\mHnHsHh}hd>\mHnHsH! jh}hd>\mHnHsH h2>^Jaaabbbcc&c.ccccCdDdEdFdGdHdtdudvddddddddd f8g:g@gúïèÑzvnvfvb^Vh:hj45hj4hhh9\6h|h9\6h9\ jh9\h5ah9\^J jh9\ h}^Jhh'b56 h'b56 haO56jhD-hD-Uhhc^J hD-^J h^Jhh^J hc^J h^J h}eZ^J hY^Jh:hE5^J hE^J!@gDggggghhhhhhiiiii6iRiTiXifini|iiiȷzm`R`R`Hh'0smHnHsHh~h'0s>*mHnHsHh'0sh'0smHnHsHh'0sh'ImHnHsHhXymHnHsHh lcmHnHsHh lc\mHnHsH! jh}h lc\mHnHsHh'0sh lcmHnHsH! jh}h lc\mHnHsH h9\^J hD-^Jh^h:hL5hL jhj4 hL^J jhj4hj4hiiiiiiiiijj j j8j:j*mHnHsHhH 'hH 'mHnHsHhH '\mHnHsH! jh}hH '\mHnHsHh'0shH 'mHnHsHhH 'mHnHsH! jh}hH '\mHnHsHhT[h*mHnHsHh*mHnHsHhtRu\mHnHsH! jh}htRu\mHnHsHh'0shtRumHnHsHhtRumHnHsH! jh}htRu\mHnHsHhH 'mHnHsHhH 'hH 'mHnHsHzk|kkkkkkkkkkkkkkkkl llllll l"lflhljllllƸƸƸƸƸƸti[N[Nh ZGh ZGmHnHsHhL6 h ZG>*mHnHsHh@Ys\mHnHsH! jh}h@Ys\mHnHsHh'0sh@YsmHnHsHh@YsmHnHsH! jh}h@Ys\mHnHsHh>*mHnHsHh7whb#>*mHnHsHhb#hb#mHnHsHh'0sho#mHnHsHh:UmHnHsHho#mHnHsHho#\mHnHsHllllllllm"m&mmmmmmmmnnpntnvnxnzn˿zvrXr>r3 jh}h z5CJOJQJ\^JmHnHu3 jh}h z5CJOJQJ\^JmHnHuh zh3 jh}h5CJOJQJ\^JmHnHu h'0shh3 jh}h5CJOJQJ\^JmHnHu h^J h^J h3^J hi.G^J hC^Jh'0sh@YsmHnHsHh ZGh ZGmHnHsHhL6 h ZG>*mHnHsHznnnooo ppppppppjplpnppprptpvpxp|p~pppppppppp6qqqƿƯƯƚysmgma[ h4^J h^J hH@^J h. ^J h\p^J h^Jh0} jh0}h0}h0}^J jh0} h0}^Jh+*h+*mHsHh+* jh+*h0}h+*^J jh+* h+*^J h9\^Jhh*B56 h*B56 hi ,^Jjrbh*Bh*BU hO^J h*B^J#qq$rLrrrrrr ssss>snspssssssstt t t tt˺⭧}l^M! jh}h=7q\mHnHsHh=7qh=7q\mHnHsH! jh}h=7q\mHnHsH h&^J h3^J hN^J h>}^J hd^J h4^J h\M^J h;^J h`z^J h0}h! jh}h\mHnHsH h0J! jh}h\mHnHsH h ^J h^J h.Y^J h<^J h^J tt+t,tgthttuuu3u*mHnHsHh=7qh=7qmHnHsH&ttttttttuuuuuuuuu#u$u'u3u*\mHnHsHh'h'>*\mHnHsHh'h'\mHnHsH! jh'h'\mHnHsHh/19h'\mHnHsH jh'h'\hfKh"h^JhC h@$e^Jh"h"^J h"^J h^J hC^JLuMuRuSuTu]ucuguiujuruuuuuuuuuuuuuuuǷǚ{peTI>hZv\mHnHsHh \mHnHsH! jhU|h \mHnHsHhZv\mHnHsH jhU|h \h@(hWcmHsHhWch1PhG]h5hU|h@$ehU|mHnHsHh@$ehU|>*\mHnHsHhU|hU|>*\mHnHsHhU|hU|\mHnHsH! jhU|hU|\mHnHsHh@$ehU|\mHnHsH jhU|hU|\uvvvv$v&v4v*mHnHsHhU|h \mHnHsHh \mHnHsHJvLvjwxxxxx y:y1bhV)hmHnHsHhV)h?mHnHsHh?mHnHsHhV)hhmHnHsHhV)h;mHnHsHh;mHnHsHh;h;mHnHsHhhmHnHsHhZvhVmHnHsHhVhV>*mHnHsHhZvhV>*mHnHsHhL'h}5CJOJQJ\^JmHnHu'hL5CJOJQJ\^JmHnHu3 jhU|hL5CJOJQJ\^JmHnHu$y(y*y8y:y*mHnHsHhU|hvD\mHnHsH! jhU|hvD\mHnHsHhvDhvD\ jhU|hvD\hzh?=mh0hM1hGDh"uhx hx hx pr~ƒ=>DNOńʄф҄Մքۄ܄$ ( * 4 6 gdv,gd\gd.gdgdbD!@&gd%|~ƒƃȃʃ̃5678<=>?BCFɻַyuj\K\! jhh\mHnHsHhh\mHnHsH jhh\hO jhk hhk jhkhkhSbUhq jhxhkhxmHsH jhxhxhahbD!hbD!>*mHnHsHh)jhbD!mHnHsHhvDhbD!mHnHsHhvDhbD!>*mHnHsHhU|hbD!\mHnHsHFHKMNOYÄĄńƄɄʄЄф҄Ԅքׄ؄Ľ}m}fb^ZPChv,h\mHnHsH jh\h\hv,h\hk hmhh.h.>*\mHnHsHh.h.>*\! jh.h.\mHnHsHh.h.\mHnHsHh.h.\ jh.h.\hkL hkLhkL h.5 hhhh>*\mHnHsHhh\mHnHsH!hh6\]mHnHsH؄لڄ܄ )IMޅ  " $ & ( * , . 0 2 4 6 n          ɺ爄|xtxpi jhh?jht#h+hZh ihbh5m{hn hnh! jhv,hv,\mHnHsHhv,hv,\mHnHsHhv,hv,\ jhv,hv,\hh~Uh<hh3ZhnhEh6Xh\hv, h\h\ jh\h\&szqrni a sorokat. A (^$( az res sorokat vlogatja ki, amikben mg whitespace sincs (termszetesen ez is multiline mdban mqkdik jl). A (\b( szhatron egyezsre val. Szhatr a (\w( s (\W( tmenet, tetszQleges irnyban, gy a (\b( sz elejnek s vgnek keressre is j. Baloldalt behatrolt  al sztring: (\bal( szilva alma hatalmas almamter Az  alma sz keresse ktoldali hatrral: (\balma\b( szilva alma hatalmas almamter Egybetqs, kttag urn-ek keresse: (\burn:\w:\w\b( Pldul: urn:a:b (vagy urn:x:y) A (\B( (nagy B) nem szhatron egyezst jell ki. (\Balma( A hatalmas alma hatalma. A (\A( olyan mint a (^(, csak mindig a szveg s nem a sor elejt jelenti fggetlenl a multiline opcitl. A (\z( (figyelem, kis z) pedig olyan mint a ($(, csak mindig a szveg s nem a sor vgre mutat egyezst. A (\Z( (nagy Z) annyival engedkenyebb, mint a kisbetqs prja, hogy a szveg vgn mg lehet egy plusz soremels is. Ez amgy igaz a ($(-ra is. Vannak mg tovbbi pozcionlis kifejezsek is (pl. (?!...)), amelyekre most terjedelmi okokbl nem trek ki. [6] mindegyiket trgyalja. Pozcionlis karktereknl nagyon oda kell figyelni, hogy Windowsban a sorok vge nem \n, hanem \r\n, ami miatt sokszor nem jl mqkdnek a Unixon helyesen zenlQ regexek. Agyrm, de erre fel kell kszlni. Szmossg (Quantifiers vagy Modifiers) Amit eddig lttunk, az csak a jghegy cscsa. A regexek elsQ igazi erQssge a szmossg adta flexibilits. MirQl is van sz? Az (a( egy darab a betqt jell, fogyaszt el. Az (a?( ( a betq, utna egy krdQjel) viszont azt jelenti, hogy az  a karakter 0 vagy egyszeri elQfordulsa. Ez azt jelenti, hogy akkor is egyezst mutat, ha az adott pozcin van  a betq, de akkor is, ha nincs. Azaz a krdQjel jelentse: az elQtte levQ karakter vagy karakterosztly opcionlis. Az albbi plda trtszmokat prbl meg elcspni, a trt rsz opcionlis: (\d\d\.?\d?\d?( 13.85, 12.5, 15., 45 A (\.( a pont karaktert jelli, csak mivel az metakarakter, meg kellett vdeni egy visszafele perjellel. Lthat, hogy csak az elsQ kt szmjegy ktelezQ, az utna kvetkezQ karakterek nem. Sajnos ez a regex megengedi a  15. -t is, ami nem szablyos. Amg nem ismerjk a csoportostst, addig ezen nem tudunk segteni. A (+( 1 vagy tbb (legalbb 1) elQfordulst jell. A plda az sszefggQ szmsorokat keresi meg: (\d+( 12, 5445, 12.345, 0.33 A (*( 0 vagy tbb (brmennyi) szmossgot definil. A ponttal egytt hasznlva knnyedn lerhat a brmibQl brmennyit minta: (.*( alma - 1 tallat Ha belegondolunk, ez a minta mindenre egyezik mg az res sorra is, s a brmilyen karaktereket tartalmaz sorokra is. Tovbbi szmossgi jelzQk is lteznek. A ({n}( jelentse: pontosan n elQforduls. A plda hrom sszefggQ betqt keres: (\w{3}( Cica, kutya, sas, Qz, l, kecske Azaz nem hrombetqs szavakat keresnk, ahhoz be kell vetnnk a szhatrt is, mindkt oldalrl: \b\w{3}\b Cica, kutya, sas, Qz, l, kecske ({n,}(: legalbb n tallat. Minimum 3 digites egsz szmok keresse: (\d{3,}( 123, 5445, 12.345, 0.33, alma58942-szilva Lthatan a tizedes trt utni rszt is megtallja. Hogy azt kiszqrjk mg okostani kell a regexnket (((?<!\.)\d{3,} (, az rdeklQdQk kedvrt :) . s vgl a ({n,m}( legalbb n, de legfeljebb m darabszmot r elQ. (g{1,2}y( gyurgyalag, aggyad m Az sszes eddig ltott szmossgjelzQ moh, azaz megprbl olyan hossz egyezst sszehozni amennyit csak lehetsges. Pldul a (\w{3,}( megprblja a lehetQ leghosszabb, de minimum hrom karakter hossz betqcsoportokat megtallni: (\w{3,}( Cica, kutya, sas, Qz, l, kecske  4 tallat Azrt moh, mert nem elgszik meg a minimlisan megkvetelt darabszmmal. Brmelyik szmossgjelzQ mohsgt elvehetjk, ha mg rakunk egy krdQjelet: (\w{3,}?( Cica, kutya, sas, Qz, l, kecske  5 tallat 0 => Cic 1 => kut 2 => sas 3 => kec 4 => ske Lthat, hogy most megll a felttelt minimlisan kielgtQ szm karakternl, aztn folytatja a kerest. Ezrt vgta kett a kecskt. Gyakoroljuk kicsit az eddigieket! Hogyan keresnnk meg a kikommentezett sorokat (//) C# kdban? (???( int i; //long g; // dim i as Integer Hogyan gondolkodunk? Soreleje, majd jn utna akrhny darab whitespace, majd kt egyms utni perjel, aztn a sorvgig brmi. Elg knnyq lefordtani regexre: (^\s*//.*$( Csoportostsok (grouping) KvetkezQ hatalmas fegyvernk a csoportosts, melyet zrjelezssel rnk el. Tbbfle okbl csoportostunk: a csoportokra hasznlhatunk szmossgi jelzQket a csoportok ltal megfogott tartalomra hivatkozhatunk a regex tbbi rszben (backreferences) a csoportok ltal elkapott tartalmat kinyerhetjk programozott eszkzkkel Mivel a szmossg hasznlhat csoportokra, a korbbi trtszmokat keresQ regexnket mostmr tkletesre rhatjuk: (\d+(\.\d+)?( 13.85, 12.5, 15., 45 Magyarra fordtva: minimum egy decimlis szmjegy, aztn egy opcionlis csoport, ami bell gy nz ki, hogy egy pont, aztn minimum egy szmjegy. Azaz csak akkor fogjuk meg az egsz rsz utn ll pontot, ha utna van szmjegy, egybknt nem. Egyszerq, de nem teljes email ellenQrzQ: (\w+@\w+(\.\w+)+( soci@netacademia.net, alma%@sexybabes.com soci12@alma.korte.neta.com Visszahivatkozsok (backreferences) Tegyk fel, hogy html tagok kztti kifejezseket akarunk lerni regexszel. ElsQ nekibuzdulsunkban megszljk ezt: (<\w+>[\w\s]*</\w+>( <h1>alma</h1> s <h2> krte </h2> <p></p> Az eddigiek alapjn ennek teljesen rhetQnek kell lennie. Igen m, de ez knnyen tverhetQ: <h1>alma</xxx> - hibs! Megeszi ezt is. Valahogyan meg kellene mondani, hogy a msodik kacsacsQrs rszben azt akarjuk ltni, amit az elsQben elkapott a regex motor. Ehhez elQszr be kell zrjeleznnk az elkapand kifejezst: (<(\w+)>[\w\s]*</\w+>( Ez nem vltoztat semmit a kifejezs mqkdsn, de a regex motor mr tudja, hogy valami clunk van a zrjeles kifejezssel, ezrt megjegyzi azt. Mr csak az a dolgunk, hogy a zrtagnl hivatkozzunk a zrjeles tartalomra. Erre val a visszahivatkoz kifejezs: <(\w+)>[\w\s]*</\1> <h1>alma</xxx> s <h2> krte</h2> <p></p> A (\1( azt jelzi, hogy itt olyan tartalmat vrunk el, amit a balrl legelsQ zrjeles kifejezs fogott meg. Fontos megjegyezni a szablyt, balrl az n., mert egymsba gyazott zrjelek esetn gy knnyq megtallni, mire akarunk hivatkozni. Az (\2( a msodik, ... kifejezsre hivatkozik. A visszafel hivatkozs hatalmas lehetQsg a regexekben, s ilyet csak az NFA motorok tudnak, ezrt aztn a legtbb engine NFA. Elgazsok (Alteration) Ha a karakterosztlyoknl megadhattunk vlasztst egy karakterpozcin, akkor ezt mirt ne tehetnnk meg nagyobb regex kifejezsekre is? Erre val az elgazs, melyet a (|( (pipe, csQ, fggQleges vonal) szimblum reprezentl. A kvetkezQ regex jelentse:  alma vagy  krte karakterek egymsutnisga: (alma|krte( alma, krte, krtealma, cser, hatalmas  5 egyezs Sokfle kommentet keresQ kifejezs: (^\s*(//|#|rem|').*$( int i; //long g; ' dim i as Integer rem dos komment # unix comment Az elgazsok brmelyike lehet sszetett regex is. A kvetkezQ plda ltal ellenQrztt rtkek behatrolst a kedves olvasra bzom. (\b0\d\b|\b1\d\b|\b2[0-3]\b( 15, 28, 21, 14, 5, 142 Gondolkodtat pldk Exponencilis szmokat felfedezQ regex: (((\d+)?\.)?\d+e[+-]?\d+( 3e8, 4e+4, 5e-8, 45.6e-5, .34e-6 Fjl elrsi tbl a fjlnevet kiszedQ kifejezs: ([^/]*$( /winnt/system32/drivers/etc/lmhosts.sam Moh szmossg esetn az elsQ .* felemszt mindent, a msodik kifejezsnek csak a legutols szakaszt hagyja meg: (^(.*)/(.*)$( winnt/system32/drivers/etc/hosts.txt 0 => winnt/system32/drivers/etc 1 => hosts.txt A mohsgt csillaptva megelgszik az elsQ /-ig tart legrvidebb kifejezssel: (^(.*?)/(.*)$( winnt/system32/drivers/etc/hosts.txt 0 => winnt 1 => system32/drivers/etc/hosts.txt Mi trtnik, ha a msodik csillag mohsgt is elvesszk? Semmi vltozs nem trtnik, mert miutn az elsQ kifejezs nmegtartztat mdon csak a  winnt karaktersorozattal egyezik, a msodik minden visszafogottsga ellenre knytelen elvinni a tbbit. s a teljessg kedvrt: ha az elsQ moh a msodik nem, az elsQ felszed mindent az utols perjelig, gy a msodik kapja a maradk rszt, ha moh, ha nem. Html tagek kitakartsa, pldul frum szoftverekhez: (</?\w+[^>]*>( <html><head> <link rel="stylesheet" type="text/css" href="/css/main.css"> <title>NetAcademia - A legjobbakat tantjuk</title> </head> <b>Tanfolyami trkpek:</b><br> </html> Az eddigiek utn a kiindul pldnkban szereplQ regex mr gyerekjtk kell legyen: (\b(\w+)(\s|<[^>]+>)+(\1)\b( Ha nem, akkor rdemes jra elolvasni a cikket, s tesztprogramokkal ([4] s [5]) prblgatni a kdokat (legalbb kiderl, mennyi bug maradt benne :). Ez a leggyorsabb mdja a regex tanulsnak. Utols pldaknt tetszQleges szepatrorokkal elvlaszott, de v-h-nap formtum dtumok megtallst nzzk meg: (\D*(\d\d\d\d)\D(\d\d)\D(\d\d)\D*( Hogy ezen pldt hasznunkra tudjuk fordtani itt az ideje, hogy megnzzk programozott mdon hogyan lehet elrni a regex szolgltatsokat. Regex programozs a .NET Frameworkben Kiindul osztlyunk a System.Text.RegularExpressions.Regex lesz. Ez kpes eltrolni egy regexet, amit aztn rszabadthatunk egy sztringre. Ltrehozsakor megadhatjuk a kvnt regexet stringknt, illetve a mqkdsi opcikat a RegexOptions enumercis tpus segtsgvel: RegexOptions options = RegexOptions.IgnoreCase; Regex regex = new Regex(@"\b(\w+)(\s|<[^>]+>)+(\1)\b", options); Esetnkben lnyeges, hogy a kis-nagybetq klnbsg ellenre kt szt azonosnak tekintsnk, ezrt a RegexOptions.IgnoreCase opci. A regex ltal elkapott darabokat a kvetkezQkppen kaphatjuk meg: MatchCollection matches = regex.Matches(input); Az input a bemeneti stringnk. Az eredmnyeken knnyq vgigiterlni: foreach(Match match in matches) { Console.WriteLine("Pos: {0} ", match.Index); Console.WriteLine("1. sz : {0} ", match.Groups[1]); Console.WriteLine("Ismtls: {0} ", match.Groups[3]); } A MatchCollection az sszes megtallt kifejezst tartalmazza. Ezeket egyedi Match objektumokknt rhetjk el a ciklusban. Minden egyes Match tartalmazza azt a szveget, amit a regex elkapott. A Match.Index az egyezs pozcijt adja vissza a bemeneti szvegben. Neknk csak az elsQ s a harmadik zrjeles kifejezs az rdekes, a kzpsQ nem, annak csak az volt a dolga, hogy lenyelje a kt sz kztti html tagokat s whitespace-eket. Szerencsre a zrjelezett tartalmakat kzvetlenl elrhetjk a Match objektum Groups kollekcijn keresztl. A 0. csoport mindig a teljes Match-et tartalmazza, ezrt az elsQ zrjeles regex (((\w+)() ltal elkapott tartalmat az elsQ Group elemben rhetjk el: Console.WriteLine("1. sz : {0} ", match.Groups[1]); rtelemszerqen a 3. csoport a match.Groups[3] mgtt lesz. Mit tallunk a msodik csoportban? Nos, ez csak az igazn rdekes. ((\s|<[^>]+>)+( Ez a csoport akr tbbszr is szerepelhet az egyezsben, ezrt ezt nem lehet egyszerqen match.Groups[2]-knt elrni. Ha a bementi sztring Ez is <i>dadogsnak</i> <u>Dadogsnak</u> szmt. akkor a match.Groups[2].Value-ban  <u> -t tallunk. Pedig ha belegondolunk, a msodik csoport 4-szer is mqkdtt: egyszer elkapta a  </i> -t ((<[^>]+>(), aztn egy szkzt ((\s(), aztn mgegyet, majd a  <u> -t. A Value jellemzQ csak az utoljra elkapott darabkt adja vissza! Az sszeset a csoport Captures jellemzQjn keresztl szedhetjk elQ: int i = 0; foreach(Capture c in match.Groups[2].Captures) { Console.WriteLine("{0}.: {1}", i++, c.Value); } 0.: </i> 1.: 2.: 3.: <u> A dtumnormalizls pldnkhoz az elkapott csoportok tartalmbl kell sszelltani egy formzott dtumot, s azzal kell kicserlni a tallt, rosszul formzott dtumnak ltsz sztringet: private void Run() { string[] dates = { "2003/08/12", "2003.08.12", "2003.08.12....", "aa2003/08.12z" }; foreach(string d in dates) { Console.WriteLine("{0} -> {1}", d, Normalize(d)); } } public string Normalize(string date) { Regex r = new Regex(@"\D*(\d\d\d\d)\D(\d\d)\D(\d\d)\D*"); return r.Replace(date, "$1-$2-$3"); } 2003/08/12 -> 2003-08-12 2003.08.12 -> 2003-08-12 2003.08.12.... -> 2003-08-12 aa2003/08.12z -> 2003-08-12 A csert a Regex.Replace hajtja vgre. A $n kifejezsekkel az n. elkapott csoportra hivatkozhatunk, hasonlan a visszahivatkozsok (\n(-jhez. A kvetkezQ plda hyperlinkeket gyqjt ki egy html lapbl. A tallatokat most alternatv mdon rjk el: Regex r; Match m; r = new Regex(@"href\s*=\s*""([^""]*)""", RegexOptions.IgnoreCase); for (m = r.Match(ReadTestFile()); m.Success; m = m.NextMatch()) { Console.WriteLine("href: {0}, pozci: {1} ", m.Groups[1], m.Groups[1].Index); } href: /training/course.aspx?id=2124, pozci: 2843 href: /training/course.aspx?id=2273, pozci: 3985 Ez utbbi mdszer elQnye, hogy a regex egyeztets lpsenknt megy vgbe, gy a ciklusbl idQ elQtt kilpve a maradk rszen nem kell dolgozni a motornak. Zrsz Az eddigiek megrtse utn gyakorlati munkk elQtt mg rdemes ttekinteni a .NET Framework regexekkel foglalkoz fejezett [6], ugyanis jval gazdagabb csoportostsi lehetQsgek is vannak mg, mint amelyekrQl a cikkben olvashattak. J regexelst! Socz Zsolt  HYPERLINK "mailto:zsolt.soczo@netacademia.net" zsolt.soczo@netacademia.net A szerzQ a NetAcademia vezetQ fejlesztsi oktatja, MCSE, MCDBA, MCSD.NET, MCT A cikkben szereplQ URL-ek:[1]  HYPERLINK "http://www.unicode.org/" http://www.unicode.org/[2]  HYPERLINK "http://www.unicode.org/reports/tr8/index.html" http://www.unicode.org/reports/tr8/index.html[3]  HYPERLINK "http://tinyurl.com/qw7c" http://tinyurl.com/qw7c [4]  HYPERLINK "http://www.sellsbrothers.com/tools/#regexd" http://www.sellsbrothers.com/tools/#regexd[5]  HYPERLINK "http://tinyurl.com/ny0f" http://tinyurl.com/ny0f[6]  HYPERLINK "http://tinyurl.com/atlv" http://tinyurl.com/atlv Kapcsold tanfolyamaink:2524 - XML Webszolgltatsok fejlesztse ASP.NET segtsgvel 2349/2415 - A .NET keretrendszer programozsa C#/VB.NET nyelven     NetAcademia-tudstr Ez a dokumentum a NetAcademia Kft. tulajdona. Vltoztats nlkl szabadon terjeszthetQ. ( 2000-2003, NetAcademia Kft.  PAGE 1 6  0 v x      4 r t    vgd{/gdO1gd8ggd3gd# gd#gd^   F V j n p r t v ~          . 0 ` t v x z           ƿʹͬ|lleah[R& hh?jhFh^h^>*\mHnHsH! jh^h^\mHnHsHh^h^\mHnHsH! jh^h^\mHnHsHh#hP.hZ jht# hh?jht# jht#ht# jhQj hh?jhQj jhQjhQjh_.hh?j jhh?j hh?jhh?j%  0 2 B J p r t        "$&(*,>Fj~渴~wpwhwd`\R jh# h3h[R&hVh@h]h]6 jh] hh?jh] jh]h]h;h# h# >* jh# h# h# h#  jh# h# h# h.h#h;mHnHsHh#h#>*\mHnHsH! jh#h#\mHnHsHh#h#\mHnHsH jh#h#\ JLHTtvz|~žŰžšŝ}yung hh?jh{/ jh{/h{/hCd h>rhO1 jhO1h] hh?jhO1 jhO1hO1h>rh8gh8gmHsH jh8g hh?jh8g jh8gh8gh=h3h3>* h3h3h3h[R&mHnHsH jh# h3h3h3mHnHsH(~^  rx@BD~ &(fh{{whDs jhn jhnhnh$eh9h4h9Eh$eh35h$eh$e5 ho'5hw< h] h]h]h[h4h"5 h"h"h" jh5/ jh5/h5/hq{ hh?jh{/ jh{/h{/-BDh<^`lgdd2gd(xgd& gd$J@&gd$egd{/$:< "$(*Ѱ𚖏|xtplel^ jh jhhhTJh*DhH heAh h4 jh% jh%h%hFoh$Jh$J>*\h$Jh$J\h$Jh$J>*\mHnHsH! jh$Jh$J\mHnHsHh$Jh$J\mHnHsH! jh$Jh$J\mHnHsHh$Jh.hDshJR$\^`bhjlpt|ֻֻֻֻֻֻra! jhd2hd2\mHnHsHh?'Fhd2\mHnHsH jhd2hd2\hU h=Gh3hhhQ{ h=Gh=G jh=G jh=Gh=Gh3h& h& >*\! jh& h& \mHnHsHh& h& \ jh& h& \h>h& h(xh hh#(0 ,BZ^񹵱}vraShihi\mHnHsH! jhihi\mHnHsHhzA hyk.htih#lh8~h~i hyk.hyk. jh hyk.h jhhyk.h;zh4h2zh\2Hh?'Fhd2mHnHsHhg\mHnHsHhd2hd2>*\mHnHsHh?'Fhd2>*\mHnHsHhd2hd2\mHnHsH " $ J r          !!!!"!$!&!(!>!пyung`\XghJ; hf jhJ; hJ; hJ; jhJ; h6 h'ihsh'ih'i>* h'ih'i hshsh(Hhsh/h#9h4h8a=hzAhihimHnHsH!h8a=hi6>*\mHnHsHhihi>*\mHnHsHhihi\mHnHsH! jhihi\mHnHsH"    !!!!! "":####$$$%%%D&F&&gd:8gd)F8gdbgdsgdi>!R!v!!!!!!!!!!!!!!!!! " "&"r"x""""""".#2#6#8#:#P#R#ݴxqmie^ jhz hz hh~ jh,t h,th,t hZhZ jh,thZh4hlh9 hJ; hkmhbhb>*\mHnHsHhbhb\mHnHsHhbhb>*\! jhbhb\mHnHsHhbhb\ jhbhb\hHh4hkmhf$R#\#^#`###############$$$ $D$$$$$%%%ƸƗƗƗƊ~zvrXPh<0^h\3 jhL h5CJOJQJ\^JmHnHuhL hUhhyh!'hhD!hre/hD!mHnHsHh)F8h)F8>*\mHnHsH! jh)F8h)F8\mHnHsHhre/h)F8\mHnHsHh)F8h)F8\mHnHsH jh)F8h)F8\hd hz h6 hRhz jhz hz hz %%%%%%%%%%%&& &&*&.&0&2&B&D&F&&&v'ŷzzjzz_TzGC?Ch.h=hL h:8mHnHsHhp\mHnHsHh:8\mHnHsHhpLnh:8>*\mHnHsHhpLnh:8\mHnHsHh_>h:8>*\mHnHsHhL h:8\mHnHsH! jhL h:8\mHnHsHh<0^h:8\mHnHsH! jhL h:8\mHnHsHhL h hh3 jhL h5CJOJQJ\^JmHnHu&v'x'''' ((.(@(B(P)***,*@*l*n*++++,,>- & FgdC#@&gdl@gdhqgd&{gdagd:8v'x'z'''''''''''''''''@(B(((6)8)P))))*ͼttgc_[_W_SOKSh9Vhrh&{huqhh$hUhhahamHnHsHh:8\mHnHsH!hpLnh:86>*\mHnHsHhpLnh:8\mHnHsHhpLnh:8>*\mHnHsHhL h:8\mHnHsH! jhL h:8\mHnHsHh( h:86\mHnHsHh<0^h:8\mHnHsH! jhL h:8\mHnHsHh$ ******,*l*n**l+++++++++,,&,6,<,,,,,>--V.X..r/t/v/x/ѿѪ~zzi! jh h \mHnHsHh h2oh%]hndhC#hTsh8whehl@h) hl@hl@5h)c jh&{hhq hhqhhq jh&{hhqh{hT ]hR~h&{h&{>* jh&{h&{ h&{h&{ jh&{h&{h&{h$$>--.t/v////1112p2222334X4Z455D5gdngdJ@&gdgdGbgdFgd gdnd & Fgd%] & Fgdex/////////////00111111222D2H2ȾȾȾoaSFh h&mHnHsHh h&>*mHnHsHh hF\mHnHsH! jh hF\mHnHsHh hGbmHnHsH! jh hF\mHnHsHhTshGbhndhhY%h"FhNh h h >*\h h \h h >*\mHnHsH! jh h \mHnHsHh h \mHnHsHH2n2p2x2|222222233|3333334444&4F4H4V4X4Z4޸vfXfXfKhJhJmHnHsHhJhJ\mHnHsHhJhJ>*\mHnHsH! jhJhJ\mHnHsHhJhJ\mHnHsH jhJhJ\hh4hJhh5h h h}mHnHsHh h}>*mHnHsHhpC>*mHnHsHh}>*mHnHsHhGbmHnHsHh2\h}mHnHsHZ444444455505<5B5D5F5b6f6h6666667 7 77B7.8089<9켸vrn`hZhZ\mHnHsHhth%K|! jhJhOl\mHnHsHhOlhOl6\mHnHsHhJhOl\mHnHsH jhJhOl\hOlhjhh$hnhn\mHnHsHhnhn\mHnHsHhnhn>*\mHnHsHh4hJxh4hO"hPbD5F5b666 770899D999~;<<=l?n????8@:@f@t@@gd*VgdOhR@&gd:gd[gdOl<9@9B9D9h9999999999:2:r:H;J;|;~;;;;;;;;ɹ|x^VRNRx|x^RJFh@h+)hh*\mHnHsHhn hn \mHnHsHht\mHnHsHhZhZ\mHnHsHh4hZ6\mHnHsH;;<<<<< =====2>J>`>b>d>f>j>>>>?"?j?l?n?p????۹ۖrdSd! jhOhRhOhR\mHnHsHhOhRhOhR\mHnHsH! jhOhRhOhR\mHnHsHh: hBh=hOhO6hO3 jhL hB5CJOJQJ\^JmHnHu hB\3 jhL hB5CJOJQJ\^JmHnHuh:h&`hB hBhBh=h=5 h=5 h:5h\h*\mHnHsHh>*\mHnHsHh*Vh*V>*\h*Vh*V\! jh*Vh*V\mHnHsHh*Vh*V\mHnHsH jh*Vh*V\hmHsHh*VmHsHh:mHsHhOhRhR?mHnHsHh!6\mHnHsH!hAaohOhR6>*\mHnHsHhOhRhOhR\mHnHsHhOhRhOhR>*\mHnHsH@@@@@AA&AjA~A BBBBFBHBJBNBZB^BbBfBvBxBzBBBBBǿwgggZUQMIhh< h,{ h5h< hBU`mHnHsHh5h5>*\mHnHsH! jh5h5\mHnHsHh5h5\mHnHsH! jh5h5\mHnHsHhmHsHhy}mHsHhc~mHsHhBU`mHsHhmHsHh*Vh>*\mHnHsHh*Vh*V>*\mHnHsHh*Vh*V>*\mHnHsH@@@AABBJBxBzBBBB*ClCnCCCC6D8DEE8EEEgd9gdCgd gd@&gdgd5gd*VBBB&C(C*C0C4C* h h h mHnHsH jhRN(hRN(mHnHsHhRN(hRN(mHnHsH jhRN(hRN(h3DhRN(h42h$h\mHnHsHhh>*\mHnHsH! jhh\mHnHsHhh\mHnHsH! jhh\mHnHsHhUh@DtDEEEE4E6E8ElEnEEEEEEEEEEFFFFFF´ٴuqmcVRVhG1hChG1mHnHsH jhChG1hW]h*h9h9mHnHsH h9h9h9>*mHnHsHhCh9>*mHnHsHh9mHnHsHhChC>*hChC>*mHnHsH hChC jhChCmHnHsHhChCmHnHsH jhChChCh3Ehdqvh1EEEFFFFGLGNGHI|JJJK"KKLLTLdLfL MMHMJMNgd(Qgd(Qgd*kgd2#gdG1gdCFFFFFFFFGG GG8GJGLGNGGHrHHHFIHIII*JzJ|JJƼxtplhd`d\XTPLXHhq04hYhF{hiEhhgh*h4hS[h^Hh+Wjh)h,hy"hW]>*hy"hG1>*mHnHsHhy"hy">*mHnHsH h9hG1hG1>*mHnHsHhChG1>*mHnHsHhG1mHnHsHhChG1>*hw1hG1mHnHsHhw1hG1>*mHnHsH hChG1 jhChG1mHnHsHJJJJJKKKKKLBLbLdLfLMMDMFMHMMMMMMN N"N:Nh4hh4h5hhh(QmHnHsH! jh Eh(Q\mHnHsHhh(Q\mHnHsH! jh Eh(Q\mHnHsHh(Qh2#h*kh*k>*h*k hCh2# jhCh2#mHnHsH h2#h2# jhCh2#hAchYh\Ub"NOOOOQQ`QxR~SSSShTjTnUUUTVVVVV"W&WWWXgdfWgd gdhw@&gd@gd1OOOOOOOtPPPQQQQ`QpQxQzQQQahccc dhdgdgdsjgdshdgduLgdgdfW]]]]]]*^,^.^^^^^__X_d_________D`````aaa:aa¾wmbhnhhUmHsHh46mHnHsHh6;mHnHsHhsjmHnHsHhsjhsjmHnHsHhsjh/hQ^hd jhshdhshd jhshdhg)h91h-ThH9h`h,hhhfghuL6huLhHzhSP jhxhx jhx#>aaaaaaaaabFbRbZb\bhbjblbbbbbbbbbfchcccccc}voha]aV hh?h hh hh& hhd hhq hh hhdb jhhD ; jhhD ; hhD ; jhhnh hh jhhnh hhnh hh6; hh46 hhAa hhj hhU hh4 hhu hh/ccccccddeeee ff f~ff hhhhbidi8j:jBkDkHkJkXkZk,ltlln n"nnnnTo$pɽɹɵɱɭ|x|tplhqqhDh_{h`h*4W hyhyhgh0h4d jhlP+ jhlP+hlP+hyhVw-huh'h @h/h/*h(h(6h(hg) h hhyhv3h hhq hh hh? hhQ)hdldddddddee|fffffff"gNgvgggg h8h@hDhFhgd(gdygdFhhhhi^ibidiiij:j|ϜzA/t R-Y1(2쀯@ }czPʢ_ً]N1KhN+S$06lziRwΓ"%WV,ok/+3IL\R ҋ YU5uIODC09* E`;ꮾ:5S]7jyتS :Ղ5\Ik61ɼye[22T^9;ғSyMi:a&iպ-4whh/" au PLNmnWr&o??XUJFBi2Ԕɲq;_*Gޯ,SQǔp@>XJ-mY?уdaƣݫ(hYKg{Λ :wm8G{ $d'/C gަmT/~sk zݹn5PXԦIM/Y @:hzg{6 I, Մe=\@D@Q9p_]qslJn” IՊ  gH0S-EsWr$뗨o3 e!( ݄ADK$cx>jB}wimYi{n[c4J٬ZR'3o6`'tzyf/}s}7֔RRF&Ue[=]Y #i0V -3EwY%T )毡 H8鄸RebZS^uo-荒yߣhY X,NJ7놩 _2S\uwՕK\ޘ'FjEV) 0kW'<]R;y{ŒSLZ>D2dXr.[" x/D eLЧ-@af܊4rZ,Y fq|e.iTjɊt"9BOV49E3u4 2>^5ŒZ, &55=MaWl9h-_ʒEjZdut 0u {hǧ߼öߋGo*NoW4`Ob6-E e-A&i(!T蛛esrPa91c@g=ۄ!*D$8B}sPj$% esLz(T4&qcjJ2cX6& X9> cƜ iZ-Z1@ TUݮ,SUxn 1W[o"~w#[WNis\ 3>;6DBm9`o ˩2Y $HѢB yВCW&ƶ{C=깟_z=$`rwĨUʓ]>s#?^q93Ӻ:~?ԪFj+@au#h/9Y?c^V2=LnV> !T9OU,o|[׿u/yC~pr;uy·uW.ÕLXF:'C@!A"&,҄h@0wcd zONIQAj]z}EN:з&+$Ɇ$f&J,[-$P'\=tptec)&KYR l; q3P޺y?g~Ѯ.OR6mٱcG^>jn tf;=W垃kl e jeRA/ߏ|q-!F:C.ҵ<Ɗ"#OL`IK)Xs;d-4aYRㄹ "YA- Yh`O2qj#bGŀi"~k.[ZKE P{Qzq_WT2hMlC@澣[*QԹsKӵ\4޳9`A=WA Zj{ Lv~Hq'1;_O\;tؾ;Ç'iҿT ʩ 1>8>XUMdŗ~Up/[(l8tޡNؓrܨp?CStMsTC=aT깓~@('<iR!w, ㊰ Ɗv1MiŠr*NPCl! [w@ĠV so7i&s~:~wjFը^<޿)]H碞k5$S7Lh~@NsKW zpOʷŅCEz8q}/ qdG-#_L;g Tzlm|=?;d‽J]^L=b_b޺gxM? ;>Cw2ڻ{6#I}D҃^0DbOH$K7a '$9aY;lKQGT:gc<X:A,L$KFaZ'C)ɸg̀1M,᧌=|'< $ TkYgTQ> yk_~rĩO;ˀ4;4JY$pJ(fMw7fՍm~థ9;w@ZXTlVD{V]> ,(zR)n{έ7z?·.Zt62h0U+T_$IfLj:py:'eO F:i/B>xV BVzHZ݀*ldlZdOV/ۮZbO`i70kD"Ӏ*Bn@?qˣd<( !-=; #س< y=??LOOǻwyi~u'p]{imGؿnA0ei@Dv>IL@x&1О]Mxv;^sE谟y^/X6?RӌZu$<[ 0u蟻\=w{yWtn:^I{/ Iv BtbO2jŌ@ӢNkbOk9 P"ag:@4_%~|#GU0OV2YsWҘHisSPeξۻC/rwo~w=7%7 몋b?bf P8\ xwc*0ǯp~e2~{ӟ#1|L֟4/kdX4߻/}~v]S glOJYsém@瓤k;+jLHd}Fglk#LY3ﰓrZdgIhN:iuɤt9K\MNxBbsopV ]vNzq[TQ=LEx(ljV2 F>C돽z>0njceKO}Re7s͑B6~R/Xm!fHJݟvv g#? z.5@V@A'uڧػ@h^u.7i ?9ԫv+]0BzְlN oS ;gZqs:?S!rջ/ZAd8d;O{nd#AYTouӶ/þz[_R{mA !|kPUWN6V~|zC}(2Teʲy=ծpk k j0aOL@dBdVf.RLk9' {{"`Gis.!!r'!Ca'iog7W]ae3C''|S˿5 KޱfѡA~'IP'tɾ44qLe굫3?#aysn1~[(P)-2I#3@{}^'37տ$K3&x}H P 5g%=UzthZzJ{`1?蠓A"B`ˈ|frtb|d񱑉012:9<:=2>32^ sr\)-+M5+ZRR.W**|"j'd $VQ]+-%cS9>::1::96>=6>36YMf l.^Ԩ{  ?I` 1(ԲBQ” qɧ=;-@ 1@|󎫝}S6/#ɼ:YuZAdto s(25K7V>>bJA]x5&tP-"f`J;G6~; "N柮)[W7/i/Z @@LY9"=3RPh&" dϔ A3#f"@@LY9"=3RPh&" dϔ A3#f"@@LY9"R?ޘLD/^+WtF(g֫ =/tr[qz˞Tl_sO2Ԍ <\͟ٳ<=i{eGO,9˯#|zc{cyeÃd+ZD#qR5k?I؈bIםo5@.+X\d驉yṭO뉇ζ>q!,{fu++mPr" @=`ι7P?=4_/l"/ ov@raˀs8h邏vmɏeU5G SfXcY'0)\7/"B^^`ݣ XDU;i=yI%,*Y  8Mz6@ĬH y Lvւy7vkv;aAYD { u^SYeL@l;Y{eMVuh{eC6IBE&{zc$Ԟ}j8B~bbD*uKx4=!Y5IX zwulla40> 6eppgm̈́A,]) U+^]k3>JvZED rܻ#;YI |0)r"SH|:'oot32`P"DQzyz$Lv jmuUȞt>y_vr3Çj|~Ě{]k;ufj'gKMGRs|{\N5:9-?5t %㞩7h"z؀=dy= zqr~h Y^@e3;[I=Cb"С0X١Pۈ"x!@d " m5΋g0 1"#@d6.\t @bD3FpQ5"1Ȟm\"ĈgjDhc=۸p5DtĺcƱ;h8FD ;gw}Ԍ !;}{j6zF ɱBU| }@CpiV=.yuD6T+z /#O޷ {Ë,1 e6W{-0qO FD@Cs@ah缁¼"@o&+T1dO~0%"d :+uYWgtBfWTz=.ȳÓ@E !@'T՚Q:0uC7+5eY%of-?HG~rF­aO)_)dY0TG Y*"!cT)F`|9Tsz8rg *QO=dWH^W $vW}pk0LE`5ɏ;z8 =JLn<Ҙσ2LYrs5BQe> ^ LDmsGE[("LAIZ4zCSt5`̿]5yXQj!e=}$%$NP"r22Q얟L>BaO'ā: kBI^_\)\^d!V&$(=+39)nSP(`vIm!`C~"$hPB uiyG-Sb!tέUWBSk'q(5o$uRְt7*yA6@K׭_:`\"GjhC LHqQO3TsM4MS7I;p\zJ_ PŤA85) ;{qL@'{G'fٹ55 mpz Ø0 ]K/^I╴G?A"P[WN6qĩe=i6cjTUO3 (' &ɸK>Ջ/Z d y"q(aXS1Þ&)jg*<:[|:r'qL`Rz.&MvQ=y .iBJ(Xip:${d3=S[0D nb_-Ӡnb aN/~Addr\vE=krA F[9" ̈́ \4S>"8mN {#'u&VҘ"D&.hO6N{F3S` iEgc 44>>0)7@8w=u~%N>n=zΌ$%Ѷ8r7ׇY>d סs_(f #Uq";{hV/[ˤ%'F[Jݭ^hH.spg4À'r2zA: -(Q+w[aD`O}PɒۍQHLSFrQ!-l1l3"'@ϧxAϛ`RgVI`g{#Yx`%ų`Um=@6YC}8 TpȮA f|D0Y΅J=ivWZ"c9 d+LK#汌$d"<%Bq[ V5D.YҦ4T $ψM|cM{r: T8u$ ÞMKW"%}Ț'/*VԮ_Сَxn#ɑYBuɎZI (i={JEHt؜;66Zf юDf"5dx%r ·e=M ƭ9EEI;{Jؔ{O ?ۀ9"?:7  {6t<ϻ[bcC:S' ٨~0w(uY#XTX_a#;W|{6]t$iXoEN&^n,9PwnBiQЧ@vgZ/W6Kn%!)89#0%"f kaH!\'jMI,'=,Mk 4tȓ)[lkG 4;*bQC!D%kyN@Ⱃ Sz3ylfr':y:–Dge 8;ZԜx̼!ej;܃or+E/-HhvT *+-#*)Eu5ב=@u"@#e"@ {Ɓ*DGٳ=D8@Uԉ g1z q @ؓQn${ڒ*$! t!yMjjԔcOI`u`˵ x.#%0ҏ*44Ԕ&AYJ`3L @H=Ct-ݥy 10Xy1G9}6߶Q1xstۛc$rCIIioVJw#1U gb`3Μɤ&(ݫLB*LV8 fHzL tAXZ سUb"āgNDh=ۿCDd8PE" {"Ȟq:Dh{ʭas}`Wy 6#ެZƞ-j-"   @: dN+q@A羾=3Q " |hl2s=Ew(> 6*O#Bpس5=w fEv5RI($(/9#O4_L@A59vf=:ŊgrE>m+7:P=&$h*xR0Lt^e!gOڐRȞ!DqDNZЮWI nI'DLNO4dXvrInS\CXZ5Y,2D#0$(G# i3m%Fa0 6k ,!iA6>4eO`WHP:в3\9Y٪I=m`;ꢻqZWiS̔Q'CInr-BNq8ǗCABsrOVϋ7$J(s(:8r<(ǹm_"FqL;lah}3p B hB l!\)M=w;yًq]`9f[eh0o aUTȆ-?q810~tmhVy"t_UrsGgSS4 F9 Ci1m<-a4#3<֨!F_9ܬ&O)oʼ xgˋ @Ð/ΉeNCLȞi+G4 À!ޯO[=+q|DlJQ'{7ȞX+C@4qsGS3hf;챧 zDGLT@R3#2_h*=)-(  vcώ*t@Rgj CT#AD >z!@[";}|ZģL6>3ʆ, AfETnI=ޖw_t @bG3v1DhK=۲X3N<>ca%/#7UFuHƄqPl',/&#<$喕+3jG",œa]TFUGxF0QևP{ l9![ِ֓PHS+NŒ-3$NVWG5lJ=9T.jpK Zk$LBU*AƐ[(dm`%(#H x<YJ K!$72|J >fZƞrBΊrau:dLi֢%MӳRT\:Nܡ?DT,X:OEqW: -(jgzN#%g.a"GISC%@a\!a!),H C!;Z,v K%< tЮYh3֟78ȗ';֔4K/4첉5Q0J *x%KvgfRq *N֢\Qr#-ȟEI^%-4$vg^*!9AȞ@"AOsHn?%)3Զp_$λHԢD"d!{ftݭm3Aꔻ6ˑ\%Q+S(4 =.yuD6T+zj@vuG 0' MV7yŠŭ[7)z{vBspB(>* [oKϊvu ,9o0 ι%8zK}6UU K)M^҂L%AsWZPȼ&1͖` QZRnC'L88'dلs:'kfT o+)Aܖzϔ8uF1yq_VuZtǖhu'w>*/UYISSth tޅM{r2{iA*.7A |5 6E 85峛o[OPWt%o(yE-XKٓ.LNRLZ?)m_5{ JaD !"WO*7,TLa LcwddOq` &5Ia?Vi˱HPǸ[FyYvg) v%ZmSHⴵ*fiQ 4%eH0Jgk0٧C.'H-cC5Cf+J*3BPr76s* RܖA"G TAP:!m@ #@"١n#@H=C"С#NF!̹ΞrCѸŧ!86fud3{KI2S E<)jPFT miK)pڼ@{R@BْmA˔&B]P(y '-ºc4<1M#{vkXR.SьX.삢ȹIAan٘u&H=!M9&-KA֎3܀2f̓@ؓ(阋&jybdh8-/#4 12ƞPguokDGXBnOb%!b"1.h9"ȞmV"$gB@c6"f {Y;"Ȟ  @ uٳ] @d@Lo @dv)I@E3Y17Dh=ۥ$DHddW ) ;"V"-kuC^TY=/!%!b/ q wK+!{ /*GEٳmCX@^T mg-: "+@N[%#r"}e㯕R OFpiɰ'{ MeϢZ]C g &D {bUBIVДC"&PD dO\1)e=))r8(LvBaGٳ+4jfCc҂qyz U6z 7C? 8j$I>G~ۚD !j@ ѱtϑ*4Ȟ1D mhEۻk LR4[``9ѓK)J!Ma| '=s3gw@WWo4XK|NM+yz !w GDӰAA*p} ! ?_S:U}ۘRժQ7N Cu!U؊@/B^&uOQȞazD 9< Ljaܵ &a]d왙z"(A3"d=tU2).q{-cxMP{sjr|ަ5bĒY?krϻ0?uH+uks߷<7'9O1zFӈݢ\^7F^0^2e߀?knk6YނI'4=e ,@"69m@7OnYG-gO.=d' eɉ)i0$ж !GZbC=(w1fadEpIx 'BPVF7==NO\ŕ. uݸ#Gs{ #ob= hT"О`'8{LM5eOJ=Usox$ۖTckc=}Фyݻg:~}80grFFNY8}g2sGOP(X=wvqhsdnӌ1h4 j٫W5!qf '}>9IGXJeI^s'maz gzZȈmrl)CZW0S{:0zJOW%]~bp?Ѱ#K{I*GPc=n[_4IO`>>,Ȃ:0CZו>rwfS_9DZ=9 Q9@]yG,%%@ː0g<&nq}liN^ivJS1fs@?w2 ;Wvp‡flz=cO O."%bPaFjwcFٴO7Q &x\0:E {Õ_=]F^2],1˾s‡GI҄}e_-m{1;5@ܧh+6}wpӅ>3։5<|מwA]W? fMkqޞ.qOdx3^|ތ=uvSvzY'Ni [@=ljY!{xlƞI-Wr"y Pai9;"P:Ы5xgwuvc͞F+[g&{&i8|)Ɯ Owj&7f=*y H('&sO$[$E {0D=_-!TD@@D@GD@#O2Opv`L @F5\{ZS_EkȞh6" j֨uuϼw1]:M6 FADh?=}bLtGNӟ:=cO;uD +h&>l9iQ* zm>{qlV~1j;S"x3,hL!oX1MdN7{:^h?,Kc'5z^p[- &CB@=?t@ DFHg\=gͲfdQgG5tA@=w-NrDvsOgvY{(T~* GD:wDL ƞl]'u"1 g!!O)UbO(RG#D <bIPe_V,Ү]},NAL Z:r1 Ʒl^M^@sFԹWFUYDf^y!ez{$ʞ.t[88pz,@X Q?9@Ҟ26%{ se4@jNG37{ט9ny:ڦJ.$U(ӧ'SvɆTֳ{Nى.e.[GU<Hf¨QYohvvn,'9D?:|"9dqVL/w+7m ObJP+pgx3˟y4@hؓ .Gx<9]d"@M=E7$ ]!o-tkN{pW}!)6`JD 4cC.ظ똳BPIBāĥ\)IMFvo%١g;ęW,<#Li9~K^'v6;b*+LD[-P Xc_ٍ̔lF>= pg@SDHF{b=V @Pŏw-Y֛_=}ĬP#ڋ @DLmWF_&'<,5n)Vz=zV@ <sQA*5ddx6AZ=&0M mG$e{pi$;sb(zU)s"Ũ@AM&(q IENDB`oDd 10  # AbVo 礊+2obn*o 礊+PNG  IHDRusRGBnIDATx^ U>^[,@H  :ƢuAT"aP!D'28* . @{]]UwSꮪ>ͣݪϹrOWog%[vJ)u: i j&hIN4jbhz{[^Zf%VpF~3aX^PK?)ML>U))gl^N ^).|.B |c~q84";*K,!AbVg3NaX2-m|~f2>}B_( YNe3r*#L6S LJ}G|DJSf<]@"@WHd4Iw*+V$UՔRRV.gJ_ $3)IHӅJfp 3Tey=Rs&%S`Rp(G1iKrdv44 E*  k.oj"1x/|i1e Fe=<~4Uֿ0At=$y\SܑZ*e|/qɚΦЯW7#MvL >o@7LB!!F|̓[e&0+kE2ܪc۝?ucL47Wܓ;ٽ=wjjc2MUM#wsR I:7 =_ %I)2  Ƶ{$)*ǯ9whWbwuz2B:::c/x7RNy}T O;:V+?t^/+%J߬N8B037oWYq㜫$+RaZ*)YR6̲WiyֈQo1vd1i iJT(3rw+T:ƯǁNÞSqTXҧ:>>>Goz37AޥϹr_BQ0X#/XS'eMWKZqf&'~{=sõmƊtFW'RQ**Iub\WzaߔsȏǛs K[JIS3^Nɻ4q~42xhe6fGRcu/Ph_@ P C3,S[%g8 26 uj3E-#6#eYazbZJ椔F0 `n$MLvĨs9`3Pda{)6]NFQI4LvjK3&{IHƵS2b۞qKc~^C6s(oMo͔rif-TvԦTb:>1 v%HP*}j(I}DŽt"O30U8iMt9`2 =X&Pg ǔ#$cVzF`9YR`ѱN=?MMhIؕzqFGStN;ԩqѧ'YFtTT^/+$,(B.s;*Kپpݣ>z>O'h}i(Rst|vzEB r~{`] l dhP!Báe?Z.No](Oy}>Wk |VB4XrGoYSK]{#^srdjڢyFSJ 4=-MF_6? t*ar3+6o?O'u~p/O{]>5Gs[Ι:I;V\>pnk|}ԎgL͙6n7tg25A'guGo~~/%[QK3Y Ǯ]H)PLi yᝈ|FdRB3XY`I%1$)aFniI 1o6\%`{AkE D~eʟݯơ~c1+e[II]b}z"L1ѳtfqazpCV|*?L }C`w0fzfdN4u:g.2#ُ~>ub&գ} ߜ\ӏuc_sk ֗Gy{vr+sGtøyJ6;U5p,~(#rӕZYe]ݗ}{^FE_G.B 6ah8w=9Ӎ*1R2[p.JHaj(_z^L5OoXOg+UEa${UFA{vd!؊!`{a82lO$d:7dNL+R߱OÖauV J(XIN6e(f=i2 ɱXa&FѧɾIIvqKU'K :KmO[nrwmxx[ uhSqL)g>v^ƒ;409U$l==>=KaoY]Qxy?dI{GRҜad`d)yHqx/s^ܣB/p[߅h ;y(6pRũ s; KDl"CFVÓ'ѠNgIcti|CRK5َ`Lgs#)-cLcԈ-"anWgo\,E'tLda؞:e =/ߟtu@ԹҎҋ͟7J]z;F&^n%pX}x}W]:\c2rxx"#ϛJ޼/_AȲa{QEl] jVHaP؉{/ft]7\u:o[uʮ{.%]{=ٮ_ģC ~40? 4z`{́@HF< O(bi8il>rGb4ݷd(b& ٞ;u6gӦb^:}뮽O>pW'sx3 ھч Eߣaa߸Ǐ.7xͥ]_܉grW_^'gX)H*E;6|[ηY1i|Mr5kyb#g{YS ׶ v1=bA؂w$^N6a"~O1gBpձΒmWqd'3Ͻb" ~ux9?vۿ#߸I֔Ng1PN6sGEѳ.T,"G}+b龭uGmlOgǨvQx ȇ%6:nب=ѣg5}?jg9f\/v3z< eKhdJ,{ney !А}"plA({Ӈ0X.KK H]ҜAR5;>J)2f5K- ԥtY3&8S3^.>!xtWB'r7iǼ;D!911Yv H+UYV-?QKϘ_"|Ky9kNoפ?ȎeW+mjUݱթy{N00dc82NѓbLFeKUз' ,MOK]6C(vgyd{n M7\V8mیE?=yAga%փj(VPI.᪳ RXVNZoJ^|PvX{.gO: 7v>Y4{6HfjF13kv'E7vonK t ד픱 mLBLNb]agԩɰ7Mx%{vH۟;1 '_y _vƚ㭃cI3k֤R~˥g;٨(to_-U 3Rlj'K2>N{V>K)i#ֹza͸C䴦wr[M4fuSONxĘFA@ZӫK M}3Sc&G'Fq39:6clztbft46'&ԩI}jB*/iaS;bBXJc"U,,9%IJQR;w6CQ8v*:^nKj]lO]1A٠a2d7V>U.n'¥+ V1)CDG,:/>ҖLGquuAaE1PdrG~<c޸wyb I\+.<[VĄ峢RX?Х~-{LǓ<㨙ˎ[O>KlƘtaui>pɱ߻\zqzXiv E88_l] V58N<T6 4WVD/؉P9L=?_wBNFX^G'GVL[זnޔٴ]'QV  { lؽrj183sd? ñ%MlF7(UX{7t*7BJ;`b(_ndl1q2dž1"ԇN=w'iYc/&WJЙq U):iwz,cHXB `JѱөvfKL> Fѡ#K`R$@25Rس0ʸ1WzDĮdD۸h6!@@󰯔 P&R%G>m/y>{+O !OONI&6://iE@ Y:!"{HC!3=c !@Ğ-P&!@ bϘ5C-g4I1C3f B@ @" Ej@ Y:!"toIMB }uc`USBQe'\Z.Ã83tc{{ Gg;;ҳ[q:+VjƗ=W~ #Ʉ!ΞT*53/{4ڥp'W=ߚ!!</&bh$6b-}ݹ!i8WÁ@][Α=߻m3K8M [P ;>umV/bq* C,w u 1+n#;$~ͱ Muy1L8vÅ]@[]{⮻:wC[.!$`uDuؚ*%,+J12NBVN3st CqtW&{53 „]tqƵh]w W9ߤ%C;BQɹ:#MPKՋ4EqV*qpn;ÍQg.8~6)PǞ 7ZƒSgP#}A $uv9;# ,s|4.tzk3CMQ3U@窍EȖ5"x,1{2ttVKwOߓ@T%!@<0ƈ$!|rA,"TyUƹ?=i m6sǯes<`gbʕ(P]H/(zǐR(pYUP-(z.a}]@q^ƙce@UiXniHQ=yx{n1?->4$,%ku.\q׿H+_\g}6PqY>z*m<ם%͞vDH{Z4HH/(KOLgQVDҵi Qrԩ:Fk  }Ȟ==Q#%8_I B*U%fB0HR gCiMBH\po%[|PxL|eQ}()!@K3RЕU)$2j)*,Բ=m3a{x~, b $rבOyĶW+AT;2Y?|j;-nAoiMmY\]-pT:Eg HkԌ½H|ٳ( !@}wd |dXTsaRz&ue'׎)Ena DA#0:7?NZ ecIЅD';zˊ̦}u?X0=;[w̼fy6 vfzZv;سA̝2?C1@@1PT B .{ƥ%HBh-=[H[B Ğqi ҃ Z bj/Җ @{344ķ͛:.!в$=JP'nFGGy;<3[HqBh>dO#xSf|\P9V@@!@\jG)aZ! ƞ0*-e]n:)n8 3Rc!@rx߯&˚ɼ'u¢|#8’G)"_viދpI)Vj[@t#!@ }*sf͓QBUYy"V:-"HQ͊SB YA 5cO؞5M˚ aޥuǎΛǰ;4H lϺN B5In{Wʏ$TNΘ3%!!*$=[ HOBhEɞatR =\+6 L-@3 a"RKѽ+/Wb]x)^QbB>Þu׬ ' 4q&(WYtȊ xraj| {c2 {饚ud@4=H {Z+*S Nf`9\p%S𦹚$PbB @j/D Wnٲe" :aL[_/K(xc@$=W8¦lRƒ6߸tTshb;;( !M`ON+dtآf%Bz;{g^_PbB#M`Oh& h><3i1 8РH,ޗ|ON u3'8M`O*XZs#%r] 5A_W''АAqwu뷚~B͹̝v\[:OG!v+2lͅFPATCiR"z `8ҫhO:سΦ'@gKʲWAΦ+ PXSgfRS3KoSJ1c#O'gwg쏨[YW":l/\?o1aoG؞>1i[S炡l;LCͤKWdk)9`3ӚRpU]UP10:CrYSR|m[Je]Uʉg&2q{ZZc]0_xdԉt"l@$|S#*ыU0ZAֲFOo9y.H MMM zew ݏTw_7ٓu酙ݰ>=ue$%j2{%Tg 5uV򕛥o}sz/|gV=ڙU_\w맬g+LU9n!.Po}f "g-dLӒb]䘀!`{*At+6*MNvEc:|j#dD`4hπ@Og;卒N)YtJilj G<c[&#5dsR,w.>euY#?صaŕUwL_*o^cu7޾Pd))Z~Z;FC˧p!750y@:qxeo>b\ASs'%U.yvMU1o<3}\J;ٞ-"xxU|fqU*A`Dc/:}΍ ?EE}>_ݺ4؟=yRj!߼ʌ5[{t7Kjݗ~#l O "q& G@4bf޼2>/^mdѱedi٢.?=4ο7ܹ-joc(k'ʯ7EsD&__X9n_;CJ'kOyY+5ՠpܣR"gS`oN챆uQԝ7FvR]e6 x'7oϿŽy hG^D2^Wˆ1C{$Fqډ.9V*gXve HTf΃ ډlgY_.w777~?cXF+~ЈXIHqQ˜MRW^ ,{l8e6-˾̆im/n)¨<޶ap_mV2b|yNci~c*@S匔4G@5*3_Vce(tW)L`؞r*3ر+g\=IeExR"Oi*l>D8!<}Ny|g[Gs2bcP}J1m7Yȇ :ZGA9 | "6bC1)ݗ~J4ʼnOĨ+ڦ3vֶHl6+ T6v.KόZ:KNeJƦ!.|;*Cfzl66_=1^7'}O^Q`l\ϨlLrU=rC=qMj4K> ofs`[66,#NFiY]HCagdfF2u l~FF?=²I+_{(ޱ,K?W^3qd .CY!PFCY,=6΋roo^5g:핌7a~2dT MuJ;L$ [w?8F0-lwz",k몀_j'"屇f@se~ecv~"_IMrtK338\?73~-K|fZgI쩽c,u^!-+. ;aO#Å~yF "֮/^2(w鮌_7!ٗ th;Nz sGf] ڶOO#ظx!92Qak:怞E^A³clF*Jz!'Fvs}v1ck_|y!F&wHص_zlyjcWMfpG4˿ ZYńߑ'Il21ef'a|jVZ:{&{mEJXkLwn.iS`Eb4D'0WgL\QqzOxD}rޝ/\3nS\;wcNrgٍ^bi=}XYٳ(ɋI 2wY$=ao9s{zv:B\ œ}C{Vp[xun: :A`,::e5lo ijlg;زw{ik !F7Kz?|gzVgv}b䌺%6񓮚17z**j{NQ)гS*%"PPTZQE`9L#n}s<4″ v;! ؐ&=;(l,oqCjrT=v>4'O~Y@6s(A]vY;d'ce31CYz|/xn4 j%i~b ^0)e/;M0jSlm=ዘ{,Id {<%>-diҜⵢQ= Bj3!@44+C!آUhIg4$8"@V!B {ƿBpx21ߺ=/RС bvj:eM@osn؊|B@ @I!@ @Yj퓇}܃ۿ ңc/m/˱jlgjZ bOz6j hQsm%)1W=9`Ğ߆-[3?Z*0E 6U}ɡIB3IYg]\^:֑{]\R6@'!"@,*ݟrch4w_r'ڢwTPUn5}̟6]mXD#cH;5*ѡ$Iߡ.#p4=I堌pK^]mI_@ =|_ }"GٶMO'H/>tㅻ-ML-K?o#Z="+[ǥ@_v?;8۟91ؗCdoǜܺ=Lj=!B@ P*Ųʪ"ʲJYWYUf;M/=۴͗K>%n VR*A1eSՋ4E&cc *IS3>:IR % $KYߤ$C,% J]=gPLqh{^ĞTkB I7q)+_se8\d8 i8m[(=۶}T\,Uy~Id::7alEUBի/a 5e}z{kX̙Q'`W0ku(mVivg7W]7j_CA,gQhښWVWv|15931|X%cXO.:3yy+u,S_P8iDT !B`{L*sV0n%g ( U=@eZeя/Q1l6:쉀OƤcL>{ 6/q3vq\f_4EEXghl}H%25Fؼ*U&۳Z*LDeYI)ʌ4p_RJU2j)UVXtMiIM@Ԗzu"p?6ﳨ-sN|u/?ncz9uxߦ꯳FmH5 E{^+o~z~'/ puO]=x(В[Lqd`F8oW6duquHYjۊ/;&ԩ& TAG_־8hsQo8'q!q&3V|ӑ=6%$#v I@#D@؞XnY;zY`=gA%ϽNj F F3KU#DVjz J+_C{UjkB`Ԏ4bX*Zǂ~('`biC5ib"Іl?u\#~?Hkt^:h{6`s5"MRz)[pMO?.'zݓ8 .6y)=צAֈGZ|bϚS:deH7rRCowqi{{{]/{_}.zz١m{{mPq*"̿K@3&!@$Qurwroit $*D L`XEIl 7="2Ld<%W8bOPGB_<^xQ#xSTCس,um.GrW_-)}HaנdBn,nr(#!rkuՄ rGܕVۡ#;6e3̤J*[Ҹ4"iF,c[uc o]^çFCyqĖ)#=L$pA 1~ȠB Q{&92!ĞA"}nBQ&!jJg_I n,rH' RĞ-PIQ#R{G LTs[a~Dž2ĞokhCf;?o+88V۰fi|oh^]HFس/ XZ-+O5ՄpQŝ.r8qU\iw݋vTF qF5c2b $,\mf݈Rh[BgOFޖ\q26V[fn19$&}:$Ey6(M26>Fli~["h!&S7!Z =[H]p\"h g* gZC @ T !@$ bϤh#Oflpzc3 %D3@0 A $@Bn=.dVjEgpX&Z&ȼ6#!\oH! v޵R!!@Iφ_'_#P{!TfεGr/1{ ]+@{ ]3z'j"q4HA:.t^s$"-d=C;!CCH  @와F %A`yBM)ݣ,{ƿoKᤛwQGzcu'"K%=! c'G-JCUe=BEq]sa}%2e.^{/셶 ZxAcv_R"@\[tH[G+-a3-ZLr{ X/fE3%b1{2=vL{!1 vf[^~6W\`Hn% ^  `"2P_AP5^˥ךMĞqkXc)(,=AFw5w]DQ pPJ_{;ډt,~dX]cFfsQLQ(\ {6zZUbϸL3XcQ'˷EY5[2ԋm/ )c%hvkݽ}=}s{z{;;{s=\g&ӑR,gxҁسYS@L9<>}~ w>4}ǃ3?0}_ e^.rLZy{T{bsJX 🥄@3r4ؓgrss::rӕ[X-EA =͎{=}e[Z)*(j,iHRUEVU#ClĎ)|p"?t&T!@@ejiZ PMd)%B[Ng5)LrY 5t->_:f1ЕMĞi(Rmo|6ḇcλpxOK޻5SUMye)ab)W_\ӚҒ3-J9bK8W)(([=x\y*˫V=TYu"t@"lזRoD ڦY_Mys FW]:q:9Ğz>cZ.3]BWWb/C8V1#RZ5/zٽwjߎ{Ltq: L:Y7̡ĞM|D[hΪf1"S_{O˲\:sRAg&=1RpyEeYbAYlR,稼Hؗ'"=Qc[@Ybs2;ceLwthb` ϭbqf ?,ճ{z 6M_dkØ 񢳅k_Sg/ |E`iPk's>{>2{ mk"/gY2sqa(bW#@w:{FV* ( m* grڒjBQ"@%T!@$b%Մ D3J,BHq *@3 ۳S!{~R B{6u* Z:҆2R#.g=~+%KxD@5\JY{i:Ss˚žC|Hd"@YҙEװ=ߜ@Bs'sG!b.ccFjslߺ?{1|Z=i+d 3Ğ<!PĞFyB g z 5C'=!@ԃg=QBh_t]Y=@#{6%E ]BZ9!@4 ZS3|Ȼ4:* gvo@?!@$Yۓ=ؼT'Bb1B {&UN!>ĞcL%@ LbRB |=ǘJ $"@V:@{1@ID3Ju"HA%!<3ob苫U5w7]R (NyԪ*9EP)ᕒup8WJNg;;ҩtx%dR3{-Gʕ_ΞT*53/GK~k^QR&s,oddtr*iZDU@oO5K# Q0 8{~[?FIics:?u{4OK3z[:ڞNIN fH, [ltuxxн|bψڇ3"/ƅ=ۯsu g]_⽺`]>‹KZS_xn{F9GfBj왟XU ɍ3 Ó%}x֗F Ӻ thjD/YtGK7(0@MS~.i*ൣbOz0{ lj3 4@;͞  ǐ#@ k{vvv¿H%(~&BTeP?QlY#BHوF'hW`ˠ:Cw p_]TeMQ"{P|e 0gZMDҼ Ǽ<w,&+(dk5&'G{{x"pxx+H|;ƘEyс]?oɲR v1;@4RY?I#{tJGÓس}7Ϟ ۂ.zoFÞ^hcnxbφ9ɝ:]_MiלEBĞcL%@ LbRB |=ǘJ $"@V:@3|eXº6$Vm\eKq+UpIK".ѥ2 JbpyA[I y~/#h`(,j>Ğ5! &gϙ`đ{ RiFU˚:eĔ{rL" ~ϚXQ"::;:_tuٍE*V/Ğ"GZX1 {Ӱ5)/v,IC]BѤC q%Y햪%)d{ܻx9W.T!fOq8 ~(fzB/ ɝt ܅7GpB{(q\!fbFOQ}ڵkxeMiݺ8z/BP!Ǟ%Z'27xjj+9=93r_uN<)=/'^@3#f(Bվr\j&*{>1kJ|knh%ےEsUx:@""c`^K7V*\g}&t mߺ\,s\R=G/x C7A< %Kc&P3uNf"FpKCW_;{^RdG.J {n` \% )OV۹F؞8}5J/&/[LoYB5w0?TkK(psjJz4 =- @_9yZ# |*r%]3˕$\ÛlRc894+9RH&{Ǣ9"%.#0- ! g.}-+z_!dR9=OËi\DJ0-(̖G5 #>CO2v!njT3hS1ũ.cONR"T@4'aqe\iB沪OmQ y`i<>AbbUwι C]H{,oK6=Av䝡W9=Xǒ`+nÈ4d6ךwALc,QXh/%hh9M".35|Zs[2^&1O@kpҡiawC1oAwi7[|s\bԢY|b˞5UoĞl/Ξ;v};97\}1E\\Mwgak7mXFW8[n,# c$MĞ5j$kz1K'sNT"ZĞ5!!@۟I;!@G@؞f/r!L=ٮT+Bbϰ&!L=ٮT+Bbϰ&!Lh|܎p>iIc|ψQaTLĞ!ciR 46/X[]pwL#-Ka+C[l&#C`ۄ<-eX۟! cNWnFb`O b4%U7BXpʪ"!ʲJYWȪ*U&VNS:"{о e0"M+2B1L6l_"鱈u#^vX]rK.{J/r""6\߶T+N#Т8Ĝ(RYdGgAH#@MMjJܢ{,;ܢ(!t iI|r9B_z&ɸ!4JUEj'GYd@C- C]_GZZz.izۡB2UP j,^}9bk(n_3 yQ99^-%q||Sjávqady/lUW T)/+.j|4uA=!ɞCݸjv]yqʌ`ޚ~tf|\(~Op/yd(ߓJ&;];*SuYR(5@9. ko+=6Ax*yT C^ |+Ds>{~G ev;].ɞb7DnJU$ U?gnE,!e#h ˬ=& PTP*%RNJat@ӝz<5| 4xӷ)΃Y`w |PB J@QGe5?ǸU;5:SvB yKw ?bk=y?3ZQ@ v 9v۪E$$Ϟf%Y}sd\5Ing=kڞ ߟ:"x'w-|n:&vte1~q""C@PL* Y5mOG%cڶk&0C+qbT}g5j10RDi#G9 U*=k-L`q!B@8fH/oٴ$|$ǂ?4{nHQ^%qqM)Ab|yRb"rk7mJIYgpA&.O<ȲWk4|ZFz>iz?^:_` );!%N8"(+y5 FS GגqFX`'|~*Jҍ-znsshӹF҄Nn љt:S3rcWNc8!@:.ƍC@+ Q+ԑt$B x=ǔ$@; @Lu$ SHg;2Ց G3xLI"!@ĞTGBe];I"!@)=cֵvMly? $ BsgOF@ =-o8[Z6 hB;6!Z齶"vSX㱝}ECbj'-{R@==BL<8Zy@ɞـknq{{PM Z /D.o9oπ`jg j.K&"=_(=!@) { ͻg42{ԗVK/)1!@`ؓ "}HBF*!Yfli'\u@AYBg{EjNi4wh:e\Jt1]:75%wҙZ(_F%R~Bn+5_Wg{ƠFP<]W?o,'%B =Az <!K=c,!@b7)HD3BJ@ }!KjX°},5'B{33\H:!@-;׈{`Ñʄ!di;vwݛY5mT/qWX숋!@#&m`4sP@$c׺F/ȩy5\PXuk^5KkIk)KԐk WjPm ֒R^5Ƴ";~RJBj~_jY5$LK&%0.Kߗ@B @`/ZIENDB`DyK zsolt.soczo@netacademia.netyK Fmailto:zsolt.soczo@netacademia.net$$If!vh5#v:V l  06,54p DyK http://www.unicode.org/yK 0http://www.unicode.org/}$$If!vh5#v:V l0654-DyK .http://www.unicode.org/reports/tr8/index.htmlyK \http://www.unicode.org/reports/tr8/index.html}$$If!vh5#v:V l0654DyK http://tinyurl.com/qw7cyK 0http://tinyurl.com/qw7c%DyK +http://www.sellsbrothers.com/tools/#regexdyK Hhttp://www.sellsbrothers.com/tools/regexd}$$If!vh5#v:V l0654DyK http://tinyurl.com/ny0fyK 0http://tinyurl.com/ny0f}$$If!vh5#v:V l0654DyK http://tinyurl.com/atlvyK 0http://tinyurl.com/atlv}$$If!vh5#v:V l0654$$If!vh5#v:V l  06,54p }$$If!vh5#v:V l0654N@N Normal$a$ CJOJQJ_HaJmHsHtH `@` Heading 1$$dx@&[$a$5CJOJQJ\mHsH`@` Heading 2$$x<@&a$5CJOJQJ\^JmHsH`@` Heading 3$$x<@&a$5CJOJQJ\^JmHsHX@X Heading 4$$@&a$6CJOJQJ]^JmHsHDA@D Default Paragraph FontVi@V  Table Normal :V 44 la (k@(No List ZYZ l Document Map-D M CJOJQJ^JaJBb@B  HTML CodeCJOJPJQJ^JaJFV@F 1SFollowedHyperlink >*B* phO")`Kodblokkp$s<<$d%d&d'd*$-DM NOPQ]sa$"5CJOJQJ^JmHnHsH u.O. )`Alcim5CJ .OB. {)Cim 5CJ0aJ0:OR: CLead&dPCJ6U@a6 Y Hyperlink >*B*ph4@r4 :Header  p#4 @4 :Footer  p#||zzzzzzzz z z z z zzz%.v6:vCMTO_evou|b    JKLMNO 58       !./ab@fgcdv./3LM4"#,PQCDGRSW* lm| !!""&"L"M""""""(######$$$$6$7$$%% %.%U%%%&&&''I'J'T'}'~''&()))))***H*I*`*a*k*u****I+,----------........00000 1133C3g3333464N4z44444,55u6v6x66668 8!8"88888899 999999999 ::":-:.:::::::N;;;; <<)<6<7<<A=B==?l@AB B!B'B6BHBIBXBYB_BnBBBBBBBB[C\CeCjCqCrCuCvC{C|CDDDDD"EEEEEEE&F'F2FQFRFuFvFFFFFFFFFiGGcHHIIILJKLLL&L'LfMMMMMMeNfNkN}N~NNmOnOvOOOOOP#P$PjPkPtPPP5QxQyQQQQRRRRRRSSSTS^SSSSSSSS@TTTTTTTTpUqU}U~UUV7VVVRWSWaWvWwWjXXXXXXXYYYYYY!Z"Z:Z;ZZ[[[[[%\&\:\e\f\W]^^^N_O_\_________ `````````aa-aNaOaaaaaa%b&b4bYbybbbbbbcc>c?cc?cCD^FH|J!R#%v'*x/H2Z4<9;?@B@DFJOhT]>ac$ptvx4zCFGHJKMNOR[\^_`acdefhijkmnoprstuvxyz{}~" 089v::::;<<<>CJS`^:j tJvp6 &>-D5@ENXhdFh"ns(uwwx4zDILPQSTUVWXYZ]bglqw|2zExxyyyyyyy*z1zXzpzvzzzz {!{({O{g{|XXXXXXX!8 @(  NB @ S DB S  ?-|Ct OLE_LINK2 _Hlt53919978pb{|@5pc{| o9p9<q9ms9|9|mu99w9j9Dka+^C^CeCeCFF|d+bCbCiCiCFF|9*urn:schemas-microsoft-com:office:smarttagsplace8*urn:schemas-microsoft-com:office:smarttagsCity? *urn:schemas-microsoft-com:office:smarttags stockticker   ?I+3x}  y  $%,7>aiEHgmy{ @Dad|- 6 i n S Y     h o t | * / */2[fP]"TY\a!&W\q *7;DT^ahk,;W_{U^/6TV&025Y ^ !!!!!!##$$((***+m+z+++++K,b,&-+---4.7.b.e.f.j...S/Z/^/l//////0$0(00040000000011 10131F1J1q1u111111255666 6!6)696@666777"7]7h7&8-8_8c888n99I:b:\;s;q<<<<B=N=O=X=Z=a=g=m=n=x=y======5>=>P>U>>>>>>>>>;?>???????|@@ZApAAAAAAAAAIBRBBBBBCCCC>DJDDDE EEEEEdFjFUG^G[H^HvHHHHHI%I/IvI|IIIIIIIJJULaLLLM MKPRPPQQQSST!TyTT UUgUnUUUoVtVVV)W3W4W;WYY!Y%YQYZYZZS[X[[[]]]^^^^^^^ ____`M`N`W`X`` aabbccddddefffffg+g,g7gx>{>?AAfApA'B5B6BGBZB^B_BmBnBBBBBB|CCDDJDDD"E&EMEQEFFFFG GGGGGVHZHHHtIuIbJcJJJ'L+L.L/LLLfMjMMMO O(P+PQ Q>QBQRRYY"Z9Z:\d\f\j\\\W]\]n]y]^^__``aaffffgg4h:hdhihPC,nh"|*ʻ7(%db #Z!fDG~'l%6O\fDwr^+ntxV_HTx2$^`.^`.^`.^`. ^`OJQJo( ^`OJQJo( ^`OJQJo( ^`OJQJo(hh^h`. hh^h`OJQJo(h hh^h`OJQJo(h 88^8`OJQJo(oh ^`OJQJo(h   ^ `OJQJo(h   ^ `OJQJo(oh xx^x`OJQJo(h HH^H`OJQJo(h ^`OJQJo(oh ^`OJQJo(hhh^h`OJQJo(hHh88^8`OJQJ^Jo(hHoh^`OJQJo(hHh  ^ `OJQJo(hHh  ^ `OJQJ^Jo(hHohxx^x`OJQJo(hHhHH^H`OJQJo(hHh^`OJQJ^Jo(hHoh^`OJQJo(hHh^`OJQJo(hHh ^`o(hH.hpp^p`OJQJo(hHh@ @ ^@ `OJQJo(hHh^`OJQJ^Jo(hHoh^`OJQJo(hHh^`OJQJo(hHh^`OJQJ^Jo(hHohPP^P`OJQJo(hH^`o(()^`.pLp^p`L.@ @ ^@ `.^`.L^`L.^`.^`.PLP^P`L.h hh^h`hH.h 88^8`hH.h L^`LhH.h   ^ `hH.h   ^ `hH.h xLx^x`LhH.h HH^H`hH.h ^`hH.h L^`LhH.h^`OJQJo(hHh ^`o(hH.hpp^p`OJQJo(hHh@ @ ^@ `OJQJo(hHh^`OJQJ^Jo(hHoh^`OJQJo(hHh^`OJQJo(hHh^`OJQJ^Jo(hHohPP^P`OJQJo(hHhhh^h`OJQJo(hHh88^8`OJQJ^Jo(hHoh^`OJQJo(hHh  ^ `OJQJo(hHh  ^ `OJQJ^Jo(hHohxx^x`OJQJo(hHhHH^H`OJQJo(hHh^`OJQJ^Jo(hHoh^`OJQJo(hHh ^`hH.h ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h^`OJQJo(hHh^`OJQJ^Jo(hHohpp^p`OJQJo(hHh@ @ ^@ `OJQJo(hHh^`OJQJ^Jo(hHoh^`OJQJo(hHh^`OJQJo(hHh^`OJQJ^Jo(hHohPP^P`OJQJo(hH7(G~'wrl%6db ~}|#Z!\+ntHTx         >n                 j搪        6M                            R0o4^1gk_4S4E(?7z)J7^1g7v?+B&8(9xeGOd{"Aa-]ne@Az),lAv?+B]:B9C3 3`CdGAD^ T75EOO`E>F_F/lF] {>F ISH'OH,-iK,kK)%$K^K/LU]^WpNK^KvN.S8Ngabj"|a;1bT qcgpd`0exf:8EfgV~;ODh<gh9KpUh89 hi%vib^ibj#m[jyl4vk~ l4T^pmdPHoBk$FoL;ty9qdq o ) 6 #  . L6 T ] ` n x  ( J; 7? 44_H tJJWu &A_.ag4B[,*DFEVY Vl@zAP\[=9d_8DsD!4_29=DEgVp? S53:ZzeR%(+27*VaF1m4r]EM+'I$e /2hQcj z}}< z !n&!'!@!bD!*]!""5"O"##V#2#C#zj#o#t##$N`$`{$ % &u+&B>&[R&H '!'0;'rW'w(7(@(K(RN("n()+)k7)V)g)/**+*=<*g*+A+8+lP+i ,#,iD,T,V,v,64-?-^a-Xc-Vw-D-P./].yk.:/re/{/o005090V0J-191G1O1W1p1w1>$2d2l2nn2}2Yn3E4(/4q04j435i56!6j67.7;7T\7)F84L8cr8#9/19K9:D ;;.^;3<4<I<K=8a=d>> >>2>_> @@H@ @M@\N@ [@Mh@ A+ABAYAeAwAB*BCC,C4CWBW.X*PX.Y Z3Z}eZ@[S[9\j\T ]G]%]Y]b]^ ^r ^<0^Q3^yN_k_`*`)`BU`sp`s`aAaHaHua'bP(bGbZPb\UbdbcecB,cX-cWc8Xc lcdCdshdTsdwd@$e6eifalfsg@g8gHgIgfghg~|g9hEhcOhUhnhi i'i00i~i)jrIs'0s9s>sDsTs@Ys,t/t=Rt"uS?utRu: vZva]vdqv7ww8whwzwJxyyFy!y)y4y2zFzHz`z|z{{_{&{,{F{F{5m{|m{q{|%K|b|x|y}y}>}c}8~R~c~ .<#NlYd>3Sv(x+4V6X&`P`fp%&~<n#X&e9h~1S?"Q^ Sk(@ekz;zuLzxj <Cb#42NZlfxr&P_"<EjR@}g !&-TPb`{/b3p{i0} 4d}5NMs"'(HN#iBBmq:9.cq,#%+F.OXxGXYs8+Or RYZW[apx)3L)c>* >]Y G$; CM#/?ep-H? EV& &y"9vDD^HP]qq~ !Fi\pj+ ,?oOR A$ (a)RO bdj `EQx"*QWs5;z6dY%mt/<h,nux,>pCw67PUrleo8F)VAc9;t0lSlro'Nti $d..~91=XLn[':;?CZR?F[w5G0:@9Q$u k s0?y59FE#qEru0 *H96; HU_}'@uPRxy Wc|)~/46AOy*_.fO$9<o3q;V]^?kLti9V*kW] ;qXy{ 293ElT[2~33ad4^/DLu {2}50=VgS,.HZ2\KyXIc.@YKfWz#|}iE:9OZt\z`d .msyU|E-N~k5a5/G &$'k456:?h$$Jb 0\nuz-6Ond zKj}~z~{)33G]p]}uF[qZR>=GSGmbLd .p8QU~1%:8J>Hmn!(:>W#6R]]zQ{4BD\gs&|L M1v3=~CDGRSWXyYytyuyyy,z-zzz#{${i{j{k{{{|||V||||||y0-yV8 a a9@L4&\<<<< < <<<<<~~~~~~ !#$%&'()*+-./01345678:;<=>?ABD|`` `@````` `&`*`,`0`d@`4`6`8`:`<`@`F`@`J`L`N`P`R`T`@`X`Z`^```b`@`f`j`l`n`p`r`@`v`x`z`@`~`@``@` UnknownGz Times New Roman5Symbol3& z Arial;Wingdings?5 z Courier New7&  Verdana5& zaTahoma"qhINhNh!rr>4d$x$x 3QHX)?32Regulris kifejezsek Socz ZsoltboboX              Oh+'0  4 @ L Xdlt|Regulris kifejezsek Socz Zsolt Normal.dotbobo3Microsoft Office Word@@ː@N8@N8Nh՜.+,D՜.+,X px   NetAcademia$xG Regulris kifejezsek Title `6>n    _PID_HLINKS eBook-title eBook-authoreBook-filenameeBook-ThumbPatheBook-CoverPatheBook-SpinePath eBook-PPCThumbPath eBook-PPCCoverPathA(*q+http://tinyurl.com/atlv|xhttp://tinyurl.com/ny0fNU $http://www.sellsbrothers.com/tools/regexdr` http://tinyurl.com/qw7c .http://www.unicode.org/reports/tr8/index.htmle5http://www.unicode.org/ w#mailto:zsolt.soczo@netacademia.netRegulris kifejezsek Socz Zsolt0311regex.lit  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`bcdefghijklmnopqrstuvwxyz{|}~Root Entry F0;SData '1TableaWordDocument;SummaryInformation(DocumentSummaryInformation8CompObjq  FMicrosoft Office Word Document MSWordDocWord.Document.89q