![]() |
|
||||||
|
|
| 07.02.12 / 23:26 |
|
Martin Rebane
Regulaaravaldised on elukad algajate hirmutamiseks ja mingi sünktaksi alusel otsimiseks/asendamiseks...Hea näide on parem kui tuhat halba seletust Antud juhul otsisime tekstist lõiku, mis algaks sõnaga on ja lõppeks sõnaga kah, ning vahel võivad olla mingid suvalised muud sümbolid/tähed/numbrid. PHP kood:
<?php
Kui me asendaksime teksti: ...oleks tulemus ikka sama. Niisiis, kui on vaja otsida/asendada midagi varieeruvat, tulevad appi regulaaaravaldised. Arvatavasti on paljud neid seni endalegi teadvustamata juba ammu kasutanud(nt Windowsi all faile otsides kirjutanud *.txt - ka see on regulaaravaldis). Milleks regulaaravaldisi ei kasutata? Regulaaravaldised ei ole mõeldud tavalisteks tekstis asendamisteks. Kui sul on vaja asendada kindlat teksti, siis selleks on str_replace funktsioon. Regulaaravaldiste kasutamine tavaliseks asendamiseks on serveriressursside raiskamine, kuna nood võtavad tunduvalt rohkem serveriaega kui tavalised tekstifunktsioonid nagu str_replace. Alustame algusest ehk süntaksist Seletame lahti esimese näite: . - tähistab ükskõik millist sümbolit, välja arvatud reavahetus * - tähistab nulli või enamat sümbolit .* kokku annavad seega: null või rohkem suvalist sümbolit, mis ei ole reavahetused. See kõik sulgude sisse ning lihtne regulaaravaldis ongi valmis. Lihtsad näited tere - leiab lõigu, mis sisaldab stringi 'tere', selle leidmiseks ei ole aga vaja regexpe kasutada, kui sul midagi sellist vaja on, siis kasuta strstr($string, 'tere');^tere - leiab lõigu, mis algab stringiga 'tere' (nt 'terekest ise kah!')tere$ - leiab lõigu, mis lõppeb stringiga 'tere' (nt 'joo, duud! ise kah tere')[ter] - leiab lõigu, mis sisaldab tähti 't', 'e' või 'r'. Seda tänu kantsulgudele seal ümber, kui soovid leida midagi, mis sisaldaks ainult väikeseid tähti, kasuta [a-z], suurte tähtede jaoks [A-Z] ja numbrite jaoks [0-9], [a-zA-Z] peaks seevastu matchima juhul, kui string sisaldab ainult suuri v väikeseid tähti. Neidsamu asju saab kirjutada ka teisiti:[a-Z] on sama mis [[:alpha:]][a-zA-Z] on sama mis [[:digit:]][a-zA-Z0-9] on sama mis [[:alnum:]],tühiku leidmiseks kasuta [[:space:]][^tre] - ^ tähendab ebasoovitavaid sümboleid, st hetkel ei tohi otsitavas sisalduda 't', 'e', 'r' tähte.Kui soovid kantsulgude vahele panna ka '-' ilma, et see tähendaks vahemikku, siis pane see kõige viimasena: [ter-]Kvantiteet ehk kui palju me tahame... Sa soovid ehk leida kindlat kogust sümboleid? No problem. t{1} - ok, kui olemas on ainult 1 't't{5} - ok, kui olemas on täpselt 5 't'-dt{1,5} - ok, kui olemas on 1 kuni 5 't'-dt{3,} - ok, kui olemas on 3 või rohkem 't'-dNatuke teise nurga alt: t* - 0 või rohkem 't'-dt+ - 1 või enam 't'-dt? - 0 või 1 't'-dPOSIX-tüüpi regexp funktsioonid PHP4's: ereg - tavaliseks tõstutundlikuks otsinguks eregi - tavaliseks tõstutundetuks otsinguks ereg_replace - tõstutundlik asendamine eregi_replace - tõstutundetu asendamine split - array(jada) koostamine regexpide abil(tõstutundlik) spliti - array(jada) koostamine regexpide abil(tõstutundetu) ning sql_regcase, mis muudab otsingustringi tõstutundetuks. Mõned näited Me tahame, et stringis sisalduksid ainult tähed-numbrid ning et oleks vähemalt üks sümbol. Teeme ära! Kõigepealt vaatame, mis tähti vaja on. Et hõlmata kogu stringi, paneme alguse ja lõpu paika(muidu võiks iga sümbol stringist eraldi sobida): String peab olema üks või rohkem tähemärki pikk: ...ja kogu kood on selline: PHP kood:
Emaili sobitamine Tahad teda, kas kasutaja sisestatud email on õige? Kontrollime. Esmalt vaatame kõige tähtsamat komponenti - kas @ on olemas. Nüüd teame, et eespool ätti võib olla nii tähti, numbreid, alakriipse kui ka punkte: Kuna valikuvariante on mitmeid(täht, number, alakriips, punkt), siis paneme esmalt sulud Sinna sisse tähed, numbrid: Siis alakriipsu Siin kasutasin | sümbolit, mis tähendab 'või' Edasi võib meil olla ka punkt: Ahaa, aga mida see kurakaldkriips siin teeb!? Lihtne, punktil on nimelt regexp süntaksis kindel tähendus ja ta tähendab 'ükskõik milline sümbol, va uus rida'. Seega peab ta kurakaldkriipsuga ära taandama, muidu on meie pisike regexp metsas ja email võiks sisaldada ka nt hüümärki, küsimärki jne :( Aga hetkel läheb ikkagi läbi nt selline aadress: !kala?mala@mina.ee. Miks? Sest kaks asja on puudu. 1) Määrama ära, kus kohast email algab(^) 2) Määrame ära sümbolite kvantiteedi(+ ehk üks või rohkem) OK, tundub, nagu oleks korras.. oot! aga kui keegi paneb emailiks tere..tere@ise.kah, siis läheb ju kahe punktiga asi ka läbi! Vaatame seda asja: Tõstsime asju veidi ringi, nüüd võib esimene osa olla selline: ((kokku 0 või 1 punkt või alakriips)(üks või rohkem tähte/numbrit)) Ning selliseid blokke kokku kas üks või rohkem. Ja kõige ette paneme veel tähekontrolli(esimene sümbol ei tohi ju olla mingi punkt või kriipsuke!) Esimene osa peaks korras olema, seal tohivad olla ainult tähed, numbrid, alakriips ning punkt.. ning seda vähemalt üks või rohkem ja õiges järjekorras kah veel. Nüüd tagumise osa juurde! See koosneb kolmest osast: 1) Domeen(üks või enam nimeosa(tähed-numbrid - üks või rohkem - +), võib(ei pruugi - ?) lõppeda punkti või sidekriipsuga) 2) Punkt - peab olema! Ja tema eest ei tohi olla teist punkti ega sidekriipsu, vaid tähemärk. 3) Esimese taseme domeen(.ee/.com/.info/.museum vmt). 2 või enam tähte. ja lõpp ka: Ning valmis! Kogu kood on selline: PHP kood:
Regulaaravaldiste optimiseerimine Üks tähtsamaid asju regexpide juures on, et neid õieti kasutataks. Kuna nad kulutavad üpriski palju serveriressursse, siis oleks tark tegu neid õieti koostada. Üks lihtsaim viis neid optimiseerida on kasutada case-sensitive e tõstutundlikku varianti. Selles võid ise veenduda, kui proovid võrrelda kahte sõna: Tõstutundetul variandil on variante ju võrratult rohkem. Üsnaga - seal, kus võimalik, kasuta alati case-sensitive regexpi. Seega avastame, et ka meie e-maili kontrollimine skript on natuke kohmakas! Pole lugu, asendame kõik [a-zA-Z] lihtsalt [a-z]'ga ja [[:alnum:]] [a-z0-9] ning [[:alpha:]] [a-z]'ga. Kuna email ei ole tõstutundlik, siis võime vabalt selle väiketähtedeks konvertida. Kuigi see paneb natuke koodi juurde, on see siiski kiirem kui tõstutundlik regexp. Niisiis: PHP kood:
Teksti asendamine Asendamine ise on lihtne, töötab põhimõttel: Võtame sama emaili näite ja muudame mingi teksti sees kõik emailid linkideks. Selleks eemaldame regexpist alguse ja lõpu märgid ning paneme kogu asja sulgudesse. PHP kood:
\0 tähendab kogu seda tükki, mis sobis meie ette antud parameetritega(ehk siis praegu email); \1 sümboliseerib kõige äärmist sulgu. Niimoodi saad kasutada ka mõnda sügavamat sulgude sees olevat stringi. Nt kui oleks regexp: '(tere(ise(kah)))', siis selle puhul oleks \0 ja \1 'tereisekah'; \2 oleks 'isekah' ning \3 oleks 'kah'Kui oleks regexp: 'kala(mees( ja havi))', siis selle puhul oleks \0 'kalamees ja havi'; \1 oleks 'mees ja havi' ning \2 oleks ' ja havi'*** Regulaaravaldised ei ole lihtsad, aga vast veendusid isegi, et nad on äärmiselt loogilised ning väikese mõtlemise tulemusel üsnagi söödavad. Head isu ;) .martin. Artikli kommentaarid |
|