S obzirom da se veliki broj ljudi interesuje za filtriranje, regexe i sl. rešio sam da im bar delimično olakšam i prevedem uputstvo za Perl... Za neke reči je teško naći pravi prevod pa sam ih ostavio u "izvornom obliku" tj. na engleskom... Recimo: Pattern - šema, šablon, obrazac na osnovu koje se izdvaja tekst Regullar Expression (u daljem tekstu regex) se koriste za izdvajanje delova teksta na osnovu odredjene zadate šeme - regexa iz nekog većeg teksta, linije teksta i sl. Postoje male razlike u implementaciji regexa u raznim programima, ali su osnove iste... Simboli obično daju posebna značenja šablonima. Počeću nabrajanje od najstandardnijih simbolaČ \ Citira sledeći znak; Ukoliko je neki znak specijalna naredba za regexe da bi ga predstavili kao običan simbol moramo koristiti "\" ^ Početak linije . Bilo koji znak (osim nove linije "CR/LF") $ Kraj linije | Logička operacija "ILI" () Grupisanje regexa (ili pod-paterni) [] "Klasa" znakova Klase zaslužuju dodatno objašnjenje. U okviru klase može se zadati opseg simbola koje spadaju u patern. Recimo kada su potrebna samo neka slova [asdf] -> Nalazi slova "a" ili "s" ili "d" ili "f" [a-n] -> Sva slova od "a" do "n" ili brojevi [1-50] -> Brojeve 1,2,3,4,5 ili 0 ili neki složeniji uslov... Uobičajeni "množioci", ponavljanje prethodnog paterna: * Ponovi 0 ili više puta + Ponovi 1 ili više puta ? Ponovi jedanput ili nijednom {n} Ponovi tačno "n" put {n,} Ponovi minimum "n" puta {n,m} Ponovi najmanje "n" ali ne više od "m" puta Ako se vitičasta zagrada "{}" pojavi negde drugde, onda se tretira kao obican znak. "*" Ekvivalent "{0,}" "+" Ekvivalent "{1,}" "?" Ekvivalent "{0,1}" gde su "n" i "m" su celobrojne vrednosti do 65536 Podrazumevana vrednost ponavljanja nad podpatern-om je "greedy", odnosno "pohlepan". Ovo znači da će biti odgovarajući što većem tesktu, sve dok omogućava ostatku paterna da bude pronadjen. Ako da neki množilac sto manje puta pronadje patern onda se nakon njega treba staviti "?". Značenje množioca se ne menja stavljanjem "?", već se samo menja "pohleponost" nekog paterna. Evo sad malog primera: Tekst: "Neki tekst koji sadrzi brojeve 234, slova bla, bla, bla i jos brojeva 453. Toliko je dovoljno za primer..." Kada bi želeli da izdvojimo ceo tekst do nekog broja koristili bi sledeći regex: "(.*)\d" (naravno bez znakova navoda) Rezultat bi bio: 00) Neki tekst koji sadrzi brojeve 234, slova bla, bla, bla i jos brojeva 453 01) Neki tekst koji sadrzi brojeve 234, slova bla, bla, bla i jos brojeva 45 00) Ceo patern 01) Prvi podpatern (u zagradi) Dakle šta se ovde desilo? Paternu (.*) je odgovarao ceo tekst. Da bi ispunio i drugi deo paterna "\d" - jedan broj, izabrao je ceo tekst do poslednjeg broja u liniji... Da bi izabrali samo deo teksta do prvog pojavljivanja nekog broja stavićemo "?" posle ".*"... Dakle, sada regex izgleda ovako: "(.*?)\d" I ".*?" će naći ceo tekst do prvog pojavljivanja sledeceg paterna "\d", odnosno slova... Rezultat: 00) Neki tekst koji sadrzi brojeve 2 01) Neki tekst koji sadrzi brojeve Nadam se da je ovo dovoljno da objasni upotrebu "pohlepnosti" regexa... Postoji mnogo specijalnih paterna koji pocinju sa "\" i slovom ili brojem iza "\". Neki primeri su: \t tab (HT, TAB) \n nov red (LF, NL) \r return (CR) \f form feed (FF) \a alarm (bell) (BEL) \e escape (ESC) \033 Oktalno predstavljanje ASCII simbola \x1B Heksadecimalno predstavljanje specijalnih ASCII simbola Kao dotatak su definisani i neki dodatne specijalne kombinacije: \w Neki alfa-numerički simbol (slova+brojevi+"_") odnosno "reč" \W Suprotno od \w (sve osim slova, brojeva i "_") \s Prazno mesto ("space", blanko) \S Sve osim space-a \d Bilo koji broj \D Sve osim broja Mogu se koristiti i unutar klasa, ali ne i kao oznaka pocetka ili kraja opsega. Takodje su definisani i "paterni nulte dužine" tj. specijalni slučajevi koji služe za ograničavanje paterna: \b Nalazi granicu(početak ili kraj) reči (reč = slovo, broj ili "_") \B Sve osim granice reči \A Pocetak stringa \Z Kraj reda, ili upravo pre novog reda, na kraju teksta \z Kraj reda (stringa) Granica reči "\b" je definisana kao mesto između dva znaka koji imaju "\w" sa jedne i "\W" sa druge strane (bez obzira na redosled), gde se imaginarni znakovi početka i kraja niza znakova računaju kao da pripadaju paternu "\W". Unutar klase znakova "[]" patern "\b" predstavlja "backspace"- znak za brisanje, a ne granicu reči. Podešavanje internih opcija Ako postoji potreba da se zanemare razlika izmedju malih i velikih slova, ili promeni default mod onda se koriste sekvence koje zaobilaze default podešavanja. i Zanemaruje razliku izmedju malih i velikih slova (mod CASELESS) m mod MULTILINE s mod DOTALL x mod EXTENDED Mod CASELESS Ako je ova opcija uključena slovu u paternu odgovara i malo i veliko slovo. Mod MULTILINE U startu je najčešće podešeno da se tekst tretira kao da se sastoji od jedne "linije" (čak i ako u stvari sadrži nekoliko oznaka nove linije (CR ili CR/LF)). Džokerskom znaku za početak linije "^" odgovara samo početak linije, dok džokerskom znaku kraja linije "$" odgovara samo kraj linije ili upravo pre granice "novog reda" (CR/LF). Ako je uključen mod MULTILINE džokerskim znacima za početak i kraj linije odgovaraju znaci upravo iza i upravo ispred oznake novog reda, respektivno, a takodje i početak i kraj celog teksta. Ako se ne koristi "\n" (oznaka sledećeg reda) ili "^" ili "$" onda uključivanje MULTILINE moda nema efekta. Dakle jedina razlika je u ponašanju džokera za početak i kraj linije. Mod DOTALL Ako je ovaj mod uključen onda džokeru "." u paternu odgovaraju svi znaci uključujući i nove linije. Kada je isključen nove linije se ne računaju. Mod EXTENDED Kada je ovaj mod uključen, prazna mesta (space) su potpuno ignorisana osim kad su "escape-ovano" ("\s") ili unutar klase znakova. Mislim da je ovo dovoljno za početak... U okviru regexa postoje jos mnoge zanimljive kombinacije, ali pošto ih još ni sam nisam dobro proučio ovde ću stati... Još ću samo navesti neke primene regexa u filtriranju spama... Pošto ja koristim Hamster, primeri će biti napisani za njega, ali se vrlo lako mogu prilagoditi XNews-u, Gravity-ju, Agentu i ostalim manje poznatim čitačima newsa... Najčešći filter je po adresi spamera... Postoji nekoliko manje-više sličnih načina zapisa filtera... Najjednostavniji je prosto nadovezivanje na kraj regexa i razdvajanje simbolom "|" što znači "ILI"... -9999 From {spamer1@provajder\.domen|spamer2@provajder\.domen} Ovde treba napomenuti da je poželjno ostaviti (ili dodati= "<" ispred e-maila, jer u slučaju da je spamer koristio kratku adresu, recimo "spam@eunet.yu", filter bi pokupio i adrese "nickNOSPAM@eunet.yu"... Takodje kad se dodaje adresa treba sve "." zameniti sa "\.", i isto touraditi sa ostalim simbolima koji imaju (ili mogu imati) specijalno značenje u regexu... Takodje neki ljudi praktikuju grupisanje spamera po provajderu radi optimizacije regexa... U tom slučaju regex izgleda ovako: -9999 From {(spamer1|spamer2)@provajder\.domen} Unutar "()" smo grupisali sve "ILI" naredbe, iza čega sledi zajednički deo "@provajder\.domen" Dakle ovim smo postigli da se deo regexa iza "@" nece ponavljati unutar regexa, a time ce i izvršavanje biti brže. Sledeći (takodje čest) filter je po naslovu poruke (Subject-u). -100 Subject {prodaj*|kupuj*|povoljno|cenovnik|rezanj*|nareziv*|zarad*|otkup|snimanj?|je[vf]tin} Ovde se pojavljuje jedna velika zabluda (čak i kod poznavaoca regexa). Po nekom automatizmu svi stavljaju na kraj reči zvezdicu. Ovo je zapravo greška, jer je zvezdica namenjena ponavljanju regexa, a ne pronalazenju bilo kog znaka... U ovom konkretnom slucaju: {prodaj*|kupuj*|itd. ^ ^ Znači "ponavljaj 'j' beskonačno puta"... Dakle ovo ocigledno nije ono što smo hteli. Ipak ovaj filter ce raditi, iako nije najefikasniji. Zato se ovaj filter treba izmeniti u kompaktniju i efikasniju varijantu: -100 Subject {prodaj|kupuj|povoljno|cenovnik|rezanj|nareziv|zarad|otkup|snimanj|je[vf]tin} On će nalaziti poruke koje sadrže i "prodajem" i "na prodaju" i ostale varijacije tih reči... Nije objašnjeno jediino značenje konstrukcije "je[vf]tin". Ovaj patern će pronaći reči "jeftin" ili "jevtin", jer bukvalno znači: "'je' iza čega sledi 'v' ili 'f', iza čega sledi 'tin'". Naravno po zelji dodati i ostale reči koje se pojavljuju u spamu, ali ne treba preterivati i stavljati prekratke reči jer mogu pogoditi i neke druge reči u kojima se sadrže... Recimo u ovom slučaju je upotrebljeno reč "otkup" i tom paternu bi odgovarala i reč "potkupljivati" i sl. Zato oprezno sa ovim filterom... Takodje se može primeniti i filter za cene. Pošto je ovo kompleksniji regex, ne treba ga koristiti kao takozvani "kill filter" jer je moguce da pogodi i ne-spam poruke: -200 Subject {\d+\s?(dem|dm)} Pošao sam od pretpostavke da se cena obično predstavlja brojem i valutom, a izmedju može da se nadje i prazno mesto... Dakle da raščlanimo regex: \d+ Broj jednom ili više puta \s? Sa jednim praznim mestom ili bez njega (dem|dm) Iza čega sledi valuta, najčešće marke sa oznakom "dm" ili "dem" Takodje može biti zanimljiv i filter za ponavljanje simbola u naslovu poruke, jer po običaju spameri stavljaju gomilu, recimo zvezdica da bi "istakli" svoje poruke. -10 Subject {[\^\*\(\)\+\$~@#%&<>]{2,}} Ovde smo jednostavno napravili listu svih znakova čije ponavljanje se najčešće koristi u spam porukama. Prvih nekoliko simbola su "escape"ovani, odnosno odredjeno je da se smiboli koji predstavljaju "naredbe" tretiraju kao obični simboli. To je uradjeno kod podvučenih simbola: [\^\*\(\)\+\$~@#%&<>] ^ ^ ^ ^ ^ ^ Ostali simboli ne predstavljaju specijane naredbe, ali ako nije sigurno da je neki simbol (svi osim slova i brojeva) specijalna naredba treba je u simbol dodavanjem obrnute kose crte ispred simbola... {2,} označava da se neki od simbola unutar zagrada "[]" treba pojaviti minimum dva puta, a može i više puta. Naravno ovo takodje promeniti po želji :) Ako neko ima još neki zanimljiv spam filter ili bilo kakav zanimljiv primer regexa koji bi podelio sam mnom, a i sa ostatkom news populacije može me kontaktirati na yu.comp.software ili na mail...