Cauta rapid aici ↑

Notiunii fundamentale in expresiile regulate

Ce sunt expresiile regulate ?

Sa incepem prin a raspunde la intrebarea, ce sunt expresiile regulate ? Numele este opac si nu ne spune prea multe. Expresiile regulate fac referire doar la text. Gandeste-te putin si uita-te in jurul tau pentru a vedea cat de mult text este in lumea noastra digitala moderna: e-mail, stiri, mesaje text, date de pe piata de valori, un cod de computer, contacte din agenda, oamenii etichetati in fotografii - toate aceste lucruri sunt text. Expresiile regulate sunt un instrument care ne permite sa lucram cu aceste texte prin a descrie modele de text.

Asadar, o expresie regulata este un set de simboluri care descrie un model de text. Acum este la singular. Atunci cand il vedem pluralizat vorbim despre limba oficiala a acestor simboluri, simboluri care trebuie sa fie interpretate de un procesor de expresie regulata. Vom vorbi un pic mai mult despre procesoare intr-un moment si este bine sa stiti ca procesorul este cel care face toata munca si fara el o expresie regulata nu va potrivi un text sau o bucata de text cu scopul de a manipula acel text. Acum sa ne gandim un moment si sa vedem ce sunt expresiile regulate si ce nu sunt. Expresiile regulate nu sunt un limbaj de programare chiar daca fac parte dintr-un limbaj de programare. Expresiile regulate sunt un pseudo-limbaj.

Cele mai multe limbaje de programare folosesc expresiile regulate. In expresiile regulate nu exista variabile si din acest motiv nu putem calcula 1 + 1. Expresiile regulate sunt doar simboluri care descriu un model de text si atat. In mod frecvent, veti auzi de termenul regex si reprezinta prescurtarea de la regular expression (expresii regulate).

In continuare sa vorbim despre modurile in care s-ar putea folosi expresiile regulate pentru a lucra cu text. S-ar putea sa le utilizati pentru a testa daca un numar de telefon are numarul corect de cifre sau in cazul in care o adresa de e-mail este intr-un format valid. Ai putea cauta intr-un document cu text un cuvant scris cu sau fara o anumita litera, caracter special sau dupa caz o cifra cu scopul de a face o modificare asupra acelui text. De asemenea putem cauta un text daca acesta are dupa sau inaintea lui un alt text.

Ai putea folosi expresiile regulate pentru a converti un fisier delimitat prin fila intr-un fisier delimitat prin virgula sau pentru a gasi cuvinte duplicate intr-un text. In fiecare dintre aceste cazuri, vom utiliza o expresie regulata pentru a scrie o descriere a ceea ce cautam folosind simboluri. In cazul unui numar de telefon, acel model ar putea fi de trei cifre urmate de o liniuta, urmat de alte trei cifre si o alta linie si apoi urmat de alte patru cifre. Odata ce ne-am definit modelul nostru atunci procesorul de expresii regulate (regex) va folosi descrierea noastra pentru a returna rezultatele potrivite sau in cazul testului sa intoarca adevarat sau fals daca a gasit sau nu o potrivire in textul tinta.

O expresie regulata se potriveste cu textul in cazul in care descrie in mod corect textul si pentru asta va trebui sa invatati mai tarziu simbolurile folosite in expresiile regulate insa pana atunci hai sa va spun cate ceva despre istoria expresiilor regulate.

Istoria expresiilor regulate

In aceasta sectiune vom arunca o privire asupra istoriei expresiilor regulate. Cred ca partea cea mai surprinzatoare a istoriei expresiilor regulate este ca au avut prima aparitie in domeniul neurologiei undeva prin anii 1940. In 1943, McCulloch si Pitts au dezvoltat modele care descriu modul in care functioneaza sistemul nervos uman sau modul in care o masina sau un calculator ar putea fi construit pentru a actiona mai mult ca un creier uman. In 1956, Stephen Kleene a descris aceste modele cu o algebra pe care el a numit-o seturi regulate si ulterior le-a numit expresii regulate.

Asadar numele de expresii regulate este dat de Stephen Kleene si este cel care le-a dat viata si la momentul respectiv acestea nu faceau parte din era digitala pana in anul 1968 cand Ken Thompson un pionier al calculatoarelor si unul dintre dezvoltatorii cheie ale UNIX au pus in aplicare expresiile regulate in interiorul unui editor de text UNIX si pe care el l-a construit si i-a dat denumirea ED. Acesta este punctul in care expresiile regulate au intrat in lumea computerelor si se intampla chiar acolo, la nasterea sistemului UNIX. Asadar sistemul de operare UNIX si expresiile regulate au pornit in acelasi timp in era digitala.

Acum daca ai fi un utilizator al acestui editor de text [ed] si ai vrea sa cauti un text cu ajutorul unei expresii regulate, acest lucru s-ar face prin tastarea literelor →ag← si apoi →/←, iar apoi setul de simboluri care formeaza expresia regulata pentru ceea ce ai vrut sa cauti si la final din nou →/← si litera →p←. Literele →g← si →p← au fost si raman modificatori. Litera →g← reprezinta acronimul de la cuvantul →global← si reprezinta cautarea la nivel global in textul tinta iar →p← reprezinta acronimul de la →print← cu referire directa la a printa, afisa rezultatele pe ecran. Asadar inaintea acronimului →re← (regular expression) s-a adaugat litera →g← (global) si la sfarsitul acronimului s-a adaugat litera →p← (print) si asa a luat nastere un alt acronim →grep← si dupa cum va dati seama reprezinta Global Regular Expression Print.

In lumea UNIX se intelege rapid termenul de grep si inseamna ca doresti sa cauti cu ajutorul unei expresii regulate. Termenul de grep a devenit atat de popular incat a devenit de fapt un limbaj de sine statator, astfel incat ai putea cauta in sistemul de fisiere UNIX un fisier sau mai multe fisiere cu o anumita denumire si din acest motiv a devenit foarte util in alte programe UNIX.

Mai mult decat atat, sistemul UNIX si grep au devenit atat de popularii incat au fost introdusi in universitati iar aceste universitati au predat apoi urmatoarea generatie de stele pe calculator folosind sistemul UNIX. Asadar expresiile regulate nu numai ca au ajutat la raspandirea sistemului UNIX dar sau ajutat si pe ele insele in acest fel. De-a lungul anilor 1970 sistemul UNIX devine atat de popular incat incepe sa evolueze si odata cu el si expresiile regulate si din acest motiv apar primele probleme cu expresiile regulate. Acum exista o problema in evolutia limbajului ce defineste expresiile regulate si asta pentru ca avem un set de simboluri care definesc in mod clar ceva care se potriveste si ceva care nu se potriveste.

Ei bine, daca incepeti sa schimbati sintaxa acestor simboluri, atunci vom crea probleme de compatibilitate. Imaginati-va daca ati avut un caracter de baza, care nu a avut o semnificatie speciala intr-o singura versiune, dar apoi intr-o versiune viitoare dintr-o data ii dati o alta semnificatie. Toate acele expresii regulate nu ar mai functiona si nu s-ar mai potrivi cu motoarele vechi de interpretare si nu ar mai fi in masura sa proceseze noile expresii regulate. In plus fata de grep, una dintre primele modificari este ca s-a introdus un nou program numit →egrep← sau →grep extins←. Puteti obtine, de fapt, acelasi comportament de egrep in interiorul grep folosind optiunea E dupa grep.

Asa ca →grepe← este in esenta acelasi lucru ca si egrep. Pe masura ce se adauga noi functionalitati in limbaj si lucreaza tot mai multi programatori la acest limbaj, putem spune ca de aici apar primele incompatibilitati iar in 1986, toata lumea care era implicata in dezvoltarea limbajului propune un standard, pe care il numesc →POSIX← si reprezinta acronimul de la Portable Operating System Interface Unix iar litera X este de la sistemul de operare UNIX.

Asa ca POSIX este un standard care este proiectat pentru a asigura compatibilitatea intre diferite sisteme de operare. Deci, primul lucru pe care il face este ca vor fi doua tipuri diferite de expresii regulate. Primul este reprezentat de →bres← ce reprezinta expresii regulate de baza si in esenta este grep si →eres← ce reprezinta expresii regulate extinse.

Acum, nu este de asteptat ca →bres← si →eres← sa fie interschimbabile, dar cel putin avem doua cai clare inainte. Termenul de bres mai poarta denumirea prescurtata si de BRE (basic regular expression) si este foarte folosit pentru a mentine compatibilitatea cu instrumentele vechi iar eres este ceea ce instrumentele moderne vor folosi. Asa ca tot acest efort de a standardiza intr-un fel toate ideile implementate in expresiile regulate ne-au adus mai aproape de conceptul din prezent ce face referire la modul cum expresiile regulate ar trebui sa functioneze. In acelasi timp Henry Spencer scrie o librarie regex in limbajul de programare C.

Ce e minunat este faptul ca este o librarie si ca poate fi incorporata in alte programe si de aceea ofera consistenta pentru ca atunci toti cei care utilizeaza libraria, expresiile lor regulate vor functiona in acelasi mod. Asa ca lucrurile la acest moment au devenit mai consistente si modificarile expresiilor regulate s-au stabilizat. In anul 1987, Larry Wall creaza limbajul de programare Perl. Acesta foloseste libraria regex Spencer si de-a lungul timpului i se adauga multe caracteristici mai puternice iar adevarata misiune Perl a fost sa incerce si sa fie un limbaj de programare care a fost proiectat pentru a fi cu adevarat util.

Din cauza acestor caracteristici puternice, devine intr-adevar standardul de aur al modului in care oamenii doresc ca librariile lor regex sa lucreze. Multa lume scrie in acest moment alte limbaje de programare iar majoritatea doresc ca libraria standardizata sa functioneze asa cum Perl facut-o. Deci, toate aceste caracteristici incep sa se strecoare si avem limbaje si programe Perl compatibile. Asa ca C, C++, limbajele .NET, Java, JavaScript, MySQL, PHP, Python si Ruby se straduiesc sa fie compatibile cu limbajul de programare Perl. Exista o librarie numita librarie PCRE care este compatibila cu Perl si libraria Regular Expression.

Motoare sau interpretori de expresii regulate

Anterior am vazut cum expresiile regulate sau raspandit la un numar diferit de limbaje si cum aceste limbaje sunt diferite intre ele, pentru ca ruleaza in diferite medii, tot asa si expresiile regulate devin usor diferite chiar daca se incearca sa se pastreze standardele BRE (basic regular expression) si ERE (extended regular expression) si in acest fel sa se pastreze ceea ce limbajul PERL a standardizat la expresiile regulate. Interpretoarele de expresii regulate nu au fost intotdeauna scrise de aceleasi persoane si din acest motiv acestea sunt putin diferite si pot interpreta diferit un anumit set de simboluri.

Limbajele C, C++, Java, JavaScript si ActionScript fac parte din ECMAScript si reprezinta acronimul de la →European Computer Manufacturers Association Script← si daca imi amintesc bine ECMAScript sustine standardul BRE. Limbajele .NET, Perl si PHP se bazeaza pe libraria PCRE →Perl Compatibil Regular Expression←. Exista o serie de programe diferite pe UNIX, unele care utilizeaza POSIX BRE si altele care utilizeaza POSIX ERE.

Dupa cum am spus BRE reprezinta expresii regulate de baza iar ERE reprezinta expresii regulate extinse. Prima versiune de Apache a folosit POSIX ERE iar versiunea Apache 2 foloseste libraria PCRE la fel ca si PHP, MySQL si ulterior POSIX ERE.

Fiecare interpretor de limbaj are incorporat in interior un motor sau interpretor de expresii regulate ce se doreste sa fie cat mai compatibil cu BRE sau ERE si odata cu trecerea timpului limbajele de programare sufera diferite modificari si aceste modificari pot influenta si modul in care expresiile regulate vor functiona.

Interpretor de expresii regulate pentru Javascript

In prezent toate limbajele de programare au un interpretor care executa fiecare linie de cod intr-un anumit mediu. Acest interpretor are cel mai adesea incorporat si un motor cu ajutorul caruia interpreteaza simbolurile pentru expresii regulate scrise de noi in acel limbaj.

Javascript ruleaza in prezent in medii diferite iar primul mediu in care a rulat a fost browserul. Browserele executa foarte rapid simbolurile din expresiile regulate si returneaza un rezultat cu care vom face ceva anume. Un alt mediu in care limbajul Javascript ruleaza il reprezinta editoarele moderne de text si aici ma refer la Dreamweaver sau orice alt editor de text care are incorporat interpretor al limbajului Javascript.

Exista un site web foarte bine facut cu scopul de a testa diferite expresii regulate in JavaScript iar acesta este →www.regexpal.com←. Va invit sa il vizitati si sa testati expresiile voastre regulate in limbajul Javascript pe masura ce va voi prezenta diferite simboluri cu un scop precis sau daca stiti deja sa lucrati cu expresiile regulate, atunci il puteti folosi din acest moment.

Sintaxa si moduri de lucru

Mai sus v-am vorbit despre istoria expresiilor regulate si am repetat de mai multe ori cuvantul →grep← si face referire la Global Regular Expression Print.

Sintaxa

Sintaxa unei expresii regulate reprezinta modul in care acestea sunt declarate sau scrise si dupa cum stiti expresiile regulate contin doar simboluri din diferite caractere speciale, litere si / sau cifre. Acestea vor fi asezate cel mai adesea in interiorul a doua slash-uri.

Moduri de lucru

In expresiile regulate exista trei moduri de lucru si fiecare dintre ele este reprezentat de catre o litera anume adaugata dupa cel de al doilea slash.

Modul global

Modul global reprezinta cautarea la nivel global, adica in intreg textul tinta, a textului care se potriveste cu simbolurile din expresia regulata. Vom face asta prin adaugarea literei →g← dupa cel de al doilea slash.

Modul multiline

Modul multiline reprezinta cautarea pe mai multe randuri de text din textul tinta a textului care se potriveste cu expresia regulata si la fel ca la modul anterior vom adauga o litera dupa cel de-al doilea slash. Modul multiline este reprezentat de litera →m←.

Modul case sensitive

Modul case sensitive reprezinta modul de cautare in textul tinta dupa un anumit text care se potriveste cu expresia regulata dar este scris sau are incorporat una sau mai multe litere scrise cu litera mare si la fel ca si la celelante moduri de lucru vom adauga o litera la sfarsitul ultimului slash. Litera reprezentand modul case sensitive este →i←.

Important la lucrul cu moduri

O expresie regulata poate lucra in acelasi timp cu toate aceste moduri si pentru asta puteti adauga toate cele trei litere reprezentand modul de lucru pentru fiecare in parte.

Simboluri

Caractere literare

Una dintre cele mai simple modalitati cu care putem sa potrivim o expresie regulata cu un anumit text este prin folosirea caracterelor literare. Aceste caractere literare nu sunt altceva decat diferite litere pe care le adaugam in expresia regulata pentru a potrivi un anumit set de litere din text si ca setare de baza acestea sunt case sensitive si este foarte important daca scriem aceste litere (simboluri) cu litera mare sau mica. In cazul in care vrem sa potrivim un text cu litera mare si mica atunci trebuie sa facem ca expresia regulata sa ruleze in modul case sensitive si vom face asta prin adaugarea literei →i← dupa cel de-al doilea slash.

In expresiile regulate spatiul dintre litere (simboluri) este foarte important si trebuie sa se tina cont de el daca vrem sa potrivim un cuvant ce (din greseala) contine un spatiu ce (nu) trebuie sa fie acolo.

Sa presupunem ca avem un text in care cuvantul Java se gaseste sub acesta forma sau sub forma JavaScript si despre care stim ca sunt doua limbaje total diferite si care au in comun doar acest cuvant Java.

In expresia regulata vrem sa potrivim cuvantul Java cu scopul de a-l sterge, pune sub o eticheta HTML sau orice altceva ne dorim. Pentru ca expresia sa potriveasca doar cuvantul Java fara Java din JavaScript va trebui sa adaugam un spatiu liber sau ce anume se afla dupa acest cuvant in text (un caracter special sau o cifra) dupa aceste simboluri literare ce reprezinta cuvantul Java.

/Java /i

In acest moment expresia regulata va potrivi primul text ce se potriveste cu simbolurile noastre din expresia regulata si daca mai avem in acelasi text cuvantul Java atunci pe acesta nu il va putea potrivi pentru ca expresiile regulate au ca setare de baza sa nu ruleze in modul global. Potrivirea pentru cazul in care sunt mai multe cuvinte sau text care se potrivesc cu expresia regulata se face intrand in modul global si pentru asta vom adauga litera →g← dupa cel de-al doilea slash.

Expresiile regulate sunt nerabdatoare sa returneze un rezultat dar in acelasi timp sunt si lacome pentru ca vor sa potriveasca cat mai mult si sa returneze ce a potrivit.

Metacaractere

Pana acum am vazut cum putem sa potrivim literar un caracter sau mai multe (un simbol sau mai multe) din expresia regulata cu ceea ce vrem sa potrivim in textul nostru tinta. Acum este timpul sa vorbim putin despre metacaractere.

Metacaracterele sunt diferite litere si caractere speciale care au un rol special in expresiile regulate. Acestea nu sunt multe ca numar iar unele au inaintea lor caracterul backslash →\←. Din moment ce numarul metacaracterelor nu este mare, ba mai mult, numarul lor este chiar mic, anumite metacaractere au mai multe roluri in functie de locul unde acestea se afla in expresia regulata.

Metacaracterul punct

Metacaracterul punct mai poarta denumirea si de metacaracter joker (wildcard). Acest metacaracter este unul dintre cele mai importante in expresia regulata. Pana acum am putut potrivi literar caracter cu caracter, spatiu cu spatiu, cuvinte scrise cu litera mare sau mica, cuvinte ce contin una sau mai multe litere scrise cu litera mica sau mare si care pot avea diferite caractere speciale incluse dar fara insemnatate in expresiile regulate.

Metacaracterul punct →.← poate potrivi orice caracter special care nu are o semnificarie speciala in expresiile regulate (si daca are atunci trebuie adaugat caracterul backslash inainte), litera scrisa cu majuscule ori minuscule, un spatiu sau o cifra.

Metacaracterul punct nu poate potrivi un caracter invizibil dar care este acolo si este reprezentat de rand nou sau linie noua (new line) →\n←. In cazul in care nu stiati acest caracter este adaugat de editoarele de text in momentul cand apasati tasta ENTER. Motivul pentru care acest metacaracter nu poate potrivi si →\n← este pentru ca la inceput expresiile regulate in sistemul UNIX erau facute sa ruleze doar pe o singura linie.

Este foarte important sa retineti ca metacaracterul punct va potrivi doar un singur caracter si daca vreti sa potriviti mai multe va trebui sa adaugati mai multe metacaractere punct insa nu va recomand asta pentru ca exista o varianta mai buna pentru a realiza acest lucru, insa despre asta va voi spune un pic mai tarziu.

Metacaracterul backslash

Metacaracterul backslash mai poarta denumirea si de caracter ce scapa, altereaza un rol sau schimba un rol (escape). Rolul acestui metacaracter vi l-am prezentat un pic mai devreme insa acum va spun mai multe despre el.

Asa cum am spus mai sus in expresiile regulate avem diferite metacaractere ce au diferite roluri in expresiile regulate. In textele noastre tinta putem gasi aceste metacaractere ce au o insemnatate doar in textul tinta. Pentru a potrivi expresiile noastre regulate cu diferite texte ce pot contine aceste metacaractere atunci trebuie sa adaugam metacaracterul backslash →\← inaintea metacaracterului din expresia regulata si in acest fel ii alteram rolul acestuia facandu-l sa para pentru interpretorul de expresii regulate doar un simbol simplu.

Metacaracterul backslash trebuie folosit doar pe metacaracterele carora vrem sa le alteram rolul, sa le schimbam ceea ce reprezinta in expresiile regulate si doar in interiorul unei expresii regulate si niciodata pe alte caractere (simboluri) din expresia regulata ce sunt alcatuite din litere pentru ca acestea au o insemnatate diferita sau mai bine spus un rol diferit si contin deja acest metacaracter.

Alte metacaractere

In expresiile regulate sunt cateva metacaractere care sunt reprezentate de litere iar inaintea lor este adaugat metacaracterul backslash, metacaracter ce ii schimba rolul din simbol literar intr-un cu totul alt rol.

Pana acum stim ca daca vrem sa potrivim un spatiu din textul tinta in expresia regulata va trebui sa adaugam un spatiu in expresia regulata. Exista o modalitate mai buna pentru a potrivi un spatiu cu ajutorul expresiilor regulate si nu doar atat iar mai jos puteti vedea diferite metacaractere ce vor potrivi un spatiu, o litera, un caracter special sau o cifra.

  • \s - va potrivi un singur spatiu
  • \S - va potrivi un caracter care nu este spatiu (opusul)
  • \n - va potrivi un caracter invizibil ce reprezinta o noua linie (new line)
  • \t - va potrivi un caracter tab
  • \w - va potrivi un caracter ce poate fi litera, cifra sau underscore
  • \W - va potrivi un caracter ce nu poate fi litera, cifra sau underscore (opusul)
  • \d - va potrivi un caracter digital (o cifra)
  • \D - va potrivi un caracter ce nu este digital (opusul)
  • \b - va potrivi un grup de caractere litere, cifre si/sau underscore (limita de cuvant - word boundaries)
  • \B - va potrivi un grup de caractere ce nu este limita de cuvant (ex. interiorul unui cuvant) si uneori diferite caractere speciale (opusul)
Important la metacaracterul \w

Acest metacaracter va potrivi si cifre pentru ca acestea sunt de fapt cifre sub forma de text si daca vrem sa potrivim doar cifre din text va trebui sa folosim metacaracterul →\d←. Un alt aspect foarte important la metacaracterul →\w← este ca va potrivi si caracterul special underscode →_←, acesta fiind interpretat ca fiind text.

Rolul parantezelor patrate in expresiile regulate

Parantezele patrate au un rol bine definit in expresiile regulate si daca vrem sa potrivim cu ajutorul expresiei regulate diferite paranteze patrate ce se afla in interiorul textului tinta atunci acestea trebuie sa aiba inaintea lor metacaracterul backslash.

In expresiile regulate rolul parantezelor patrate este acela de a potrivi un text ce va contine unul dintre simbolurile ce sunt in interiorul parantezelor patrate iar acestea pot fi o litera, cifra sau orice caracter special ce nu are un rol in expresia regulata si daca are atunci va trebui precedat de metacaracterul backslash.

Un exemplu util poate fi acesta in care o expresie regulata va potrivi ambele cuvinte ce contin un simbol ( o litera ) din interiorul parantezelor patrate si este important sa retineti ca nu este importanta ordinea in care aceste simboluri sunt prezentate in interiorul parantezelor patrate.

/[ai]nna/ → // va potrivi anna si inna

Metacaracterul minus

Acest metacaracter este foarte util daca vrem sa potrivim un interval de simboluri ce reprezinta litere sau cifre.

Sa presupunem ca vrem sa potrivim in interiorul parantezelor patrate un text ce ar putea contine literele cuprinse intre a si f inclusiv. Pentru a putea realiza acest lucru avem la dispozitie doua variante. Prima ar fi aceea in care am scrie toate literele alfabetului de la a la f si cea de a doua este reprezentata de folosirea metacaracterului minus intre literele a si f.

/[a-f]/

Acelasi procedeu il vom folosi si daca vrem sa potrivim cifre din text cu ajutorul expresiilor regulate.

/[0-5]/

Putem face mai mult de atat cu acest metacaracter si putem potrivi si alte intervale de litere sau cifre si asta pentru ca primul simbol fie ca este vorba de o litera sau o cifra va fi simbolul de inceput iar cel de-al doilea va fi simbolul de sfarsit.

Un aspect foarte important este acela cand vrem sa potrivim cifre cu doua numere. Sa presupunem ca vrem sa potrivim cifrele cuprinse intre 11 si 20. In acest caz nu putem scrie in expresia noastra /[11-20]/ pentru ca nu va functiona si asta pentru ca metacaracterul minus va opera doar in intervalul 0 si 9 iar acestea nu sunt cifre ci doar text. Amintiti-va ce va spuneam la inceput cand vorbeam despre expresiile regulate, expresiile regulate fac referire doar la text si nimic altceva.

Metacaracterul de negatie sau negativ

Metacaracterul de negatie este un caracter special ce probabil l-ati vazut foarte rar. Acesta se afla situat pe linia orizontala cu cifre de la tastatura la cifra 6.

Metacaracterul de negatie este unul dintre caracterele speciale ce detine mai multe roluri in expresiile regulate iar pozitia acestuia intr-o expresie regulata este foarte importanta pentru ca in functie de aceasta va avea un anumit rol.

Anterior v-am vorbit de rolul parantezelor drepte in expresiile regulate. Am vazut ca in interiorul acestora putem adauga cel mai adesea simboluri ce reprezinta litere cu scopul de a potrivi diferite cuvinte ce contin unul din simbolurile aflate in interiorul parantezelor drepte.

Metacaracterul de negatie se adauga in interiorul parantezelor drepte si intotdeauna va fi primul adaugat si plasat in partea stanga si este reprezentat in expresiile regulate de caracterul special →^←.

Prezenta acestuia in interiorul parantezelor drepte ii va spune interpretorului de expresii regulate sa potriveasca text ce nu contine literele (simbolurile) aflate in interiorul parantezelor drepte si la fel ca si la exemplul de mai sus va contine simbolurile ce urmeaza dupa parantezele drepte.

/[^ai]nna/ → // nu va mai potrivi anna si inna ci knna, qnna, onna s.a.m.d.

Metacaractere in interiorul parantezelor drepte

Metacaracterele in interiorul parantezelor drepte sunt scapate de rolul pe care acestea il au in interiorul expresiilor regulate. Aceasta este regula generala pe care vreau sa o retineti. Totusi exista cateva metacaractere care fac exceptie si asta pentru rolul pe care il au in interiorul acestor paranteze drepte. Este logic sa fie asa pentru ca altfel nu ar mai avea rolul lor bine definit si nu am mai face nimic cu ele.

Dupa cum v-ati dat seama aceste caractere sunt →^ - \ ]← si pentru a putea fi scapate de rolul pe care il au in interiorul parantezelor drepte acestea trebuie sa fie precedate de metacaracterul backslash.

Repetarea simbolurilor

Repetarea metacaracterelor

Va spuneam mai sus despre anumite caractere speciale care au un rol diferit in functie de pozitia acestuia in expresia regulata. Acum este timpul sa va spun mai multe si despre acestea.

Aceste caractere speciale nu sunt precedate de metacaracterul backslash pentru a le oferi acest rol. Simpla lor prezenta defineste un rol in expresia regulata. Daca vrem sa anulam acest rol acestor caractere speciale va trebui sa adaugam metacaracterul backslash inaintea lor si in acest fel le dam o insemnatate literara. Acum este timpul sa facem cunostinta cu aceste caractere speciale.

Caracterele speciale →+ * ?← vor extinde insemnatatea metacaracterelor ce sunt formate din caracterul backslash si o litera (fie ca este scris cu majuscule ori minuscule) sau caracterul special punct. Aceste caractere speciale ne vor ajuta sa nu mai scriem atat de mult o expresie regulata cu scopul de a potrivi un caracter sau mai multe, daca un caracter este prezent de zero ori sau de mai multe ori sau daca un caracter este prezent de zero ori sau o singura data. Practic aceste caractere speciale au aceasta insemnatate.

  • * → va testa daca simbolul este prezent de zero ori sau de mai multe ori
  • + → va testa daca simbolul este prezent o data sau de mai multe ori
  • ? → va testa daca simbolul este prezent de zero ori sau o singura data

Daca stai si te gandesti putin probabil ca rolul caracterului asterisk ti se va putea parea ciudat si te vei intreba la ce il vei putea folosi. Gandeste-te la un cuvant in care ultima litera este optionala si daca este prezenta atunci va potrivi acel cuvant din text. Pana in acel moment acel cuvant din text inseamna ceva. Hai sa va arat un exemplu.

/apples*/ → va potrivi apple, apples, appless, applesss s.a.m.d

Importanta caracterului asterisk devine evidenta in momentul cand vrem sa potrivim acest tip de cuvant sau daca un metacaracter este prezent de zero ori sau de foarte multe ori. Sa presupunem ca avem un document html in care un cod este identat incorect iar tasta tab (reprezentat in expresiile regulate de metacaracterul \t) a fost apasata de prea multe ori iar codul nu arata cum ar trebui. Acesta este un alt exemplu de care trebuie sa tineti cont in folosirea caracterului asterisk.

Caracterul special plus este cel mai folosit dintre toate trei si asta pentru ca de cele mai multe ori vom dori sa potrivim un cuvant din text ce contine unul sau mai multe litere (simboluri in expresia regulata). Dupa cum puteti vedea diferenta dintre caracterele asterisk si plus este ca in cazul caracterului plus acel simbol trebuie sa fie prezent si daca vom testa exemplul anterior vom observa ca va potrivi doar cuvintele ce contin obligatoriu litera s la sfarsit, indiferent de cate ori se repeta.

/apples+/ → va potrivi apples, appless, applesss s.a.m.d

Caracterul special reprezentat de semnul intrebarii este cel care ne va spune ca un simbol poate fi prezent sau nu si daca este prezent acesta nu poate fi repetat. Acum sa testam exemplul anterior.

/apples?/ → va potrivi apple si apples

Este evidenta diferenta dintre aceste caractere si depinde doar de noi unde si cum le vom folosi. Ce trebuie sa retineti la caracterul →?← este ca acesta il vom mai intalni pentru ca impreuna cu alte caractere speciale va avea diferite roluri.

Rolul acoladelor in expresiile regulate

Anterior v-am spus despre rolul caracterelor speciale →* + ?← in expresiile regulate. Am vazut ca doua dintre acestea vor ajuta la potrivirea unor simboluri ce contin la sfarsit un simbol ce poate fi prezent de zero ori (*) sau de nenumarate ori sau de unu ori (+) sau de nenumarate ori.

Putem face mai mult de atat in expresiile regulate mai ales daca vrem sa potrivim un cuvant din textul tinta ce va avea un numar minim si un numar maxim de litere si pentru asta vom avea nevoie de acolade. In expresiile regulate i se mai spune si repetitie cuantificata.

In interiorul acoladelor vom avea una sau doua valori reprezentate obligatoriu de cifre. In cazul in care sunt prezente doua valori atunci acestea trebuie sa fie separate obligatoriu doar de virgula, orice alt caracter va face inutila expresia regulata. Aceste cifre vor reprezenta valori minime si maxime (in aceasta ordine) ale textului pe care vrem sa il potrivim cu ajutorul expresiei regulate.

Practic ceea ce ii spunem interpretorului de expresii regulate este sa potriveasca un text ce contine un numar minim si un numar maxim de caractere.

/\w{4,10}/ → va potrivi orice cuvant ce are minim 4 si maxim 10 caractere reprezentate de litere, cifre sau underscore

In cazul in care valoarea maxima nu este definita iar virgula este prezenta atunci interpretorul de expresie regulata ii va atribui acesteia valoarea de infinit si in acest caz va potrivi orice text ce are minim 4 caractere reprezentate de litere, cifre sau underscore.

Spuneam la inceput ca in interiorul acoladelor vom putea avea si o singura valoare. Aceasta valoare devine automat o valoare fixa, o valoare ce va potrivi anumite caractere din textul tinta ce contine un anumit numar de litere sau ce vrem sa potrivim.

/\w{4}/ → va potrivi Java si Scri separat daca textul tinta este JavaScript

Calitatii ale expresiilor regulate

Expresiile regulate au cateva calitatii foarte importante iar trei dintre acestea sunt ca expresiile regulate sunt dornice (eager) sa iti returneze un rezultat, lacome (greedy) in a potrivi cat mai mult din textul tinta si lenese (lazy) in a potrivi cat mai putin. Vom testa aceste calitati prin folosirea caracterelor speciale →* + ?←, caractere ce vor fi aplicate diferit fata de ce v-am prezentat si spus pana acum.

Expresiile regulate sunt lacome

Veti vedea mai jos cum caracterul special →+← ajuta metacaracterul →\w← sa potriveasca unul sau mai multe caractere litera (word = letter, number or underscore). Acum este timpul sa il folosim si in alt scop si impreuna cu caracterul special ce reprezinta semnul intrebarii →?←.

Acum este foarte important sa ne amintim exact ce reprezinta aceste caractere luate separat. Am spus despre caracterul →+← ca va potrivi unul sau mai multe caractere si apoi am spus despre caracterul →?← ca va potrivi zero aparitii ale unui simbol sau unu aparitii ale unui simbol in textul tinta.

Testarea expresiilor regulate pentru a vedea cat sunt de lacome este prin adaugarea caracterului ce reprezinta semnul intrebarii dupa caracterul plus. Practic ii vom spune interpretorului de expresie regulata sa gaseasca si sa potriveasca cat mai mult si cu ajutorul caracterului special plus vom potrivi un caracter iar caracterul semnul intrebarii il va opri sa potriveasca mai departe. Urmatoarele exemple vor returna acelasi rezultat.

/Java?/ → va potrivi Java din Java singur sau JavaScript
/Java+?/ → va potrivi Java din Java singur sau JavaScript

Calitatea de expresie regulata lenesa

La fel ca si la calitatea anterioara, testarea calitatii de expresie regulata lenesa se va face si cu ajutorul caracterului ce reprezinta semnul intrebarii iar inaintea lui nu vom mai avea caracterul special plus ci caracterul special asterisk. Va mai amintiti ca acest caracter va testa daca un simbol va avea zero aparitii sau nenumarate aparitii. Amintiti-va inca odata ce rol are si caracterul special semnul intrebarii pentru ca este foarte important.

Ceea ce ii vom spune interpretorului de expresii regulate este sa gaseasca si sa potriveasca caracterele din textul tinta ce sunt prezente pana la penultimul pentru ca ultimul poate avea zero aparitii si este optional.

/Java*?/ → va potrivi Jav din Java singur sau JavaScript

Calitatea de dornica sa returneze un rezultat

Am vazut anterior cum calitatile de expresii regulate lacome si expresii regulate lenese sunt puse in aplicare in codurile noastre. Aceste doua calitati ne spun indirect ca expresiile regulate sunt nerabdatoare sa returneze un rezultat oricare este acela.

Gruparea si alternarea expresiilor

Gruparea metacaracterelor

Gruparea metacaracterelor in expresiile regulate se face cu ajutorul parantezelor rotunde. Totodata putem adauga in interiorul parantezelor rotunde si simboluri sau mai bine zis acele litere care nu au o semnificatie deosebita in expresiile regulate.

Motivele pentru care am dori sa folosim aceste paranteze rotunde si cu care vom grupa diferite simboluri sunt dintre cele mai diverse. Cel mai simplu motiv este acela ca in acest fel vom putea scrie o expresie regulata pe care o vom putea interpreta vizual mult mai usor. Un alt motiv este acela ca vom putea scrie mai putin intr-o expresie regulata.

/(abc){1,3}/ → va potrivi abc, abcabc si abcabcabc

Un motiv la fel de important este acela daca vrem sa potrivim un cuvant din textul tinta care are inaintea lui anumite litere.

/(in)?dependent/ → va potrivi independent si dependent

Observati ca semnul intrebarii ne ajuta in acest caz sa folosim mai mult de un simbol. Practic intreg setul de simboluri devine optional cu ajutorul caracterului special →?← si in acest fel va potrivi ambele cuvinte.

Este foarte important sa retineti ca in momentul cand interpretorul de expresii regulate detecteaza paranteze rotunde ce contin simboluri, acesta va memora ceea ce gaseste in interiorul acestora pentru a le folosi mai tarziu pentru a putea cauta inapoi in text. Aceasta modalitate poarta denumirea de backreferences despre care vom vorbi mai tarziu.

Alternarea metacaracterelor

Expresiile regulate ne permit sa folosim si mai mult rolul pe care il au parantezele rotunde. Am vazut ca putem grupa in interiorul lor mai multe simboluri ce pot fi folosite sa potriveasca un cuvant din textul tinta daca contine sau nu aceste simboluri.

Putem sa testam cu ajutorul parantezelor rotunde daca un cuvant din textul tinta are sau nu mai mult de un singur set de simboluri si pentru asta vom avea nevoie sa separam cumva aceste seturi de simboluri.

Modalitatea prin care vom putea separa aceste seturi de simboluri in interiorul parantezelor rotunde este prin folosirea caracterului special →|←. Acesta il veti gasi cel mai probabil pe aceeasi tasta cu backslash.

Este important sa retineti ca in momentul cand vom folosi acest caracter special, interpretorul de expresii regulate va testa daca acel text sau cuvant din textul tinta va avea unul dintre aceste seturi de simboluri prezente in interiorul parantezelor rotunde si separate de acest caracter.

In cazul in care reuseste sa potriveasca un set de simboluri dintre paranteze munca acestuia s-a terminat si nu il mai intereseaza sa testeze urmatorul set de caractere. Interpretorul de expresii regulate va testa de la stanga la dreapta fiecare set de simboluri si imediat ce reuseste sa potriveasca isi termina treaba si asa cum spuneam nu il mai intereseaza restul de seturi de simboluri.

/(K|A)nna/ → va potrivi Anna daca Kanna nu exista

Daca in textul tinta vom avea ambele reprezentari ale cuvantului atunci interpretorul le va potrivi pe amandoua.

/(I|A)nna/ → va potrivi Inna si Anna daca ambele cuvinte exista

Cum sa scrii logic si eficient alternarii

Am repetat mai sus cateva calitati ale expresiilor regulate iar acum vreau sa subliniez una dintre ele. Este vorba despre calitatea de dornica (eager) sa returneze un rezultat.

In momentul cand folosim alternarii in expresiile regulate, interpretorul va compara de la stanga la dreapta seturile noastre de simboluri delimitate de caracterul →|←. Interpretorul va testa primul set de simboluri cu primele caractere (litere, cifre sau ce vrem sa testam) din textul nostru tinta si daca resuseste sa potriveasca aceste prime caractere ne va returna un rezultat cu ce a potrivit. Interpretorul nu va merge mai departe sa testeze si restul de simboluri din acel grup. Interpretorul ne va returna un rezultat cu ce a potrivit din setul de simboluri din acel grup si asta pentru ca rolul caracterului →|← este sa verifice daca una dintre optiunii reuseste sa potriveasca ceva din textul tinta si imediat ce reuseste ne returneaza un rezultat cu ce a potrivit.

Din acest motiv este bine sa scriem expresiile noastre regulate dupa modelul ca daca vrem sa potrivim ceva imediat cu scopul de a testa diferite probleme din textul tinta atunci este bine sa punem aceste tipuri de alternarii la inceput si in acest fel vom scade timpul de executie al expresiei regulate prin modul ca nu va mai trebui sa caute in restul de text tinta daca alternarile noastre erau undeva pe la sfarsitul expresiei regulate. Ideea este in felul urmator. Daca este sa crape ceva atunci sa crape la inceput.

Expresii ancorate

Ancore de inceput si de sfarsit

Am repetat de mai multe ori in acest tutorial ca in expresiile regulate avem cateva caractere speciale ce vor avea mai mult de un singur rol. In aceasta sectiune vom face cunostinta si cu un alt caracter special care are un rol bine definit. Este vorba despre caracterul →$←.

Am vazut mai sus ca rolul caracterului →^← este unul de negatie in interiorul parantezelor drepte. Acum este timpul sa vedem si alt rol pe care acest caracter il are in expresia regulata.

Ancore de inceput

In expresiile regulate putem sa testam daca un text incepe cu un anumit set de litere si vom face asta cu ajutorul caracterului →^←. Acesta are rolul de ancora de inceput si va fi adaugat intotdeauna la inceputul expresiei regulate. In acest fel vom testa daca un text incepe cu diferite simboluri. Aceste simboluri, chiar daca se vor regasi apoi in text nu vor conta pentru ca rolul acestui caracter in aceasta parte din expresia regulata este de a testa daca textul respectiv incepe exclusiv cu aceste simboluri.

/^Anna/ → va potrivi primul cuvant Anna daca textul este → Anna este prietena cu Anna

Ancore de sfarsit

Opusul la ce ati vazut mai sus este reprezentat prin folosirea caracterului special →$←. Acesta va fi adaugat obligatoriu la sfarsitul expresiei regulate si va testa daca un text se termina intr-un anumit text.

/Anna$/ → va potrivi ultimul cuvant Anna daca textul este → Anna este prietena cu Anna

Folosirea acestor caractere

Am vazut cum pot fi potrivite diferite caractere din text la inceputul si la sfarsitul unui text tinta cu ajutorul acestor caractere speciale. Retineti ca pentru acest rezultat este obligatoriu ca acestea sa fie adaugate la inceputul (caracterul ^) expresiei regulate sau la sfarsitul (caracterul $) expresiei regulate.

In munca de programare vom putea testa daca un text va incepe cu diferite simboluri si se termina cu alte simboluri, dupa cum se poate vedea in urmatorul exemplu.

/^Anna.+Anna$/ → va potrivi intreg textul → Anna nu o cunoaste pe prietena Mariei pe care o cheama tot Anna

Este foarte important sa folositi modul multiline si sa rulati acest gen de expresie regulata in acest mod, in caz contrar aceasta expresie regulata va potrivi un text ce este compus doar dintr-un singur rand. Este evident si de ce potriveste un text ce contine acest text si se afla pe un singur rand. Va amintiti ca am spus mai sus ca in momentul cand apasam tasta ENTER editorul de text adauga in acel loc un caracter invizibil de linie noua sau rand nou →\n← si din acest motiv expresia regulata nu va mai potrivi intreg textul cu ajutorul simbolurilor si caracterelor speciale pentru ca randul nostru se termina in acest caracter invizibil.

Potrivirea cuvintelor

Expresiile regulate vin in intampinarea noastra a programatorilor cu doua metacaractere pe care le-am vazut un pic mai sus intr-o lista si despre care nu am spus mai nimic. Aceste metacaractere sunt →\b← si →\B←.

Metacaracterul →\b← are ca unic scop potrivirea unui grup de caractere ce pot fi alcatuite din litere, cifre si/sau underscore. Va amintiti ca underscore este interpretat ca fiind litera desi este caracter special. Mai pe scurt acest metacaracter va potrivi un cuvant sau mai multe. Aceste cuvinte pot fi alcatuite din litere si/sau cifre si/sau underscore.

Metacaracterul →\b← devine foarte util in situatia in care ne dorim sa facem expresia regulata mai usor de interpretat si sa potrivim mai usor un cuvant indiferent de cate caractere contine iar urmatoarele exemple vor potrivi acelasi text.

/\w+/g → va potrivi orice cuvant
/\b\w+\b/g → va potrivi orice cuvant

Folosirea metacaracterului →\b← ne va ajuta sa crestem viteza de executie a expresiei regulate si asta pentru ca prin folosirea lui ii vom spune interpretorului sa ne potriveasca doar cuvinte sau limite de cuvinte (word boudaries).

Metacaracterul →\B← reprezinta opusul metacaracterului →\b← si va potrivi un grup de caractere ce nu este limita de cuvant (ex. interiorul unui cuvant) si uneori diferite caractere speciale.

/\B\w\B/ → va potrivi a si v daca textul tinta este Java
\B.+\B → va potrivi litera n din textul Ana, cifra 2 din textul 123 sau chiar $%# daca este intalnit asa

Grupuri de capturare si referinte catre inapoi in text

Referinte catre inapoi in text

Va amintiti cand am spus mai sus despre modul cum putem grupa simboluri in expresiile regulate si ca vom face asta cu ajutorul parantezelor rotunde. To in acea sectiune v-am spus si ca interpretorul de expresii regulate va memora ce a potrivit cu ajutorul parantezelor rotunde pentru a putea folosi mai tarziu aceasta informatie. Aceasta tehnica mai poarta denumirea si de backreferences si desprea ea vom vorbi acum.

/h(t{2})p/ → potriveste http si retine pentru mai tarziu tt

In exemplul anterior vedeti cum functioneaza si cum interpretorul retine informatia dintre paranteze pentru a o folosi mai tarziu. Acest lucru se face automat si reprezinta o setare de baza in expresiile regulate. Nu tine cont de modul si motivele in care iti scrii expresiile regulate.

Aceasta informatie stocata de interpretor va trebui intr-un fel accesata de noi si pentru a putea accesa aceasta informatie ne vom folosi de backreferences sau referinte catre inapoi in text.

Modalitatea prin care vom accesa aceasta informatie se face cu ajutorul caracterului special →\← si urmat de un numar de la 1 la 9. Diferite interpretoare de expresii regulate iti permit sa folosesti numere de la 10 la 99 si este important sa retineti aceasta informatie daca lucrati cu expresii regulate in alte limbaje de programare. Totodata diferite interpretoare de expresii regulate vor folosi in locul caracterului →\← caracterul →$←.

/(jsdev) to \1/ → va potrivi jsdev to jsdev

Observati cum putem sa folosim referintele catre inapoi in text si sa accesam astfel informatia care este stocata cu ajutorul parantezelor sau grupari simbolurilor. Cifra ce face parte din referintele catre inapoi in text (backreferences) va face referire la a cata stocare de informatie ne referim si dupa cum am vazut in subsectiunea alternarea metacaracterelor vom putea potrivi mai multe grupuri de simboluri.

/(mar)(par)(gutui)\3\2\1/ → va potrivi marpargutuigutuiparmar

Acest exemplu are putine sanse sa fie folosit de catre voi dar principalul scop este sa intelegeti cum functioneaza referintele catre inapoi in text. Urmatorul exemplu are mai multe sanse sa fie folosit mai ales daca vom dori sa potrivim etichete HTML si continutul acestora.

/<(strong|em)>.+?<\/\1>/ → va potrivi <strong>Text</strong> si <em>Text</em>

Observati ca am folosit caractere →+?← impreuna pentru a-i spune interpretorului sa nu fie lacom si sa potriveasca doar minimul necesar.

Folosirea caracterului special semnul intrebarii in referinte catre inapoi

Pana acum ati vazut si retinut rolul caracterului special →?←. Acum este timpul sa vedeti cum acesta va poate pacali daca nu sunteti atenti in momentul cand il folositi in referinte catre inapoi (backreferences).

Stim ca prezenta caracterului special →?← ne va spune ca acel element sau grup de simboluri este optional si poate fi prezent de zero ori sau unu ori.

/(a)?b/ → va potrivi ab si b

Ce facem daca vom adauga caracterul →?← si vom face astfel optional un simbol din grup si in acest caz vom avea un singur simbol in grup.

/(a?)b/ → va potrivi ab si b

Observati ce se intampla ? Spuneam mai sus ca rolul parantezelor rotunde este de a grupa simboluri si/sau metacaractere. Totodata cand interpretorul de expresii regulate intalneste paranteze rotunde, acesta va memora ce a potrivit cu ajutorul acestor paranteze rotunde. In primul caz am avut intreg grupul optional si putea fi prezent de zero ori sau de unu ori, dupa cum ne spunea caracterul semnul intrebarii, iar in exemplul doi doar simbolul din interiorul grupului este optional iar acesta poate fi prezent de zero ori sau unu ori si din acest motiv interpretorul va retine cu ajutorul parantezelor un string cu lungimea de zero caractere. Pare putin ciudat dar interpretorul va potrivi caracterul b singur.

In JavaScript acest caz functioneaza dar in alte expresii regulate din alte limbaje de programare s-ar putea sa nu potriveasca litera b interpretorul din acel limbaj de programare si asta pentru ca sunt parerii ale specialistilor care nu au ajuns la un consens comun pentru a rezolva aceasta problema.

Cauta si inlocuieste intr-un fisier cu ajutorul referintelor catre inapoi

Putem folosi referintele catre inapoi (backreferences) in editoarele de text ce suporta expresiile regulate. Editorul de text care suporta foarte bine expresiile regulate este Sublime Text 2. Voi folosi aceasta versiune pentru a va oferi urmatorul exemplu prin care voi rearanja continutul text (ce va este aratat imediat) cu ajutorul referintelor catre inapoi.

Sa presupunem ca avem urmatorul text caruia vrem sa ii inversam numele cu prenumele.

1.Ioana Maria, Manager Senior
2.Alexandra Popescu, Entry Level Manager
3.Vali Valentin, Frontend Engineer

Mai intai trebuie sa ne asiguram ca avem editorul text Sublime Text 2 deschis si in interior acest text adaugat intr-un fisier cu extensia .txt

Urmatorul pas este sa dam click pe Find din meniul orizontal al editorului si apoi vom alege optiunea Replace din meniul aparut. Sau mai simplu vom apasa tastele Ctrl + H.

In optiunea de deasupra (Find) vom scrie urmatoarea expresie regulata ce va selecta prima cifra cu caracterul punct, apoi va selecta numele plus spatiul dintre cuvinte si in final va selecta prenumele. Toate acestea le vom grupa pentru a le utiliza imediat.

(\d\.)(\b\w+\b )(\b\w+\b)

In optiunea Replace vom adauga urmatorul cod ce va face referire la referinte catre inapoi. Editorul de text Sublime Text 2 suporta versiunea prin care in locul backslash-ului si vom adauga caracterul →$← si in final cifra aferenta grupului memorat de interpretor.

$1 $3 $2

Putem mai departe sa dam click pe Replace pentru a vedea cum sunt inversate numele cu prenumele sau Replace All pentru a le inlocui pe toate si sa terminam treaba.

Acest exemplu este foarte util si merita sa il retineti pentru situatia in care aveti un fisier .csv, .txt sau orice alt fisier text ce va contine sute sau mii de randuri cu nume, prenume, data nasteri, functia ocupata s.a.m.d. sau orice altceva si vreti sa inversati, inlocui date etc. foarte rapid scutindu-va de munca pe cateva ore sau zile.

Anularea optiunii de referinte catre inapoi

In expresiile regulate avem posibilitatea de a anula referintele catre inapoi si pentru asta vom face cunostinta cu un alt caracter special dar si cu un alt rol pe care il are semnul intrebari. Aceasta tehnica mai poarta denumirea si de non-capturing group.

Modalitatea prin care vom anula referintele catre inapoi o vom face prin adaugarea la inceputul grupului de simboluri ori metacaractere a semnului intrebarii urmat imediat de caracterul doua puncte →?:←.

Semnul intrebarii va avea rolul de a-i spune interpretorului ca acest grup de caractere are un alt rol iar caracterul doua puncte ii va spune ca rolul grupului este de a nu memora ce se potriveste cu acest grup.

Este vital sa retineti aceasta fraza si pentru rolul pe care il are semnul intrebari pentru ca il vom revedea imediat cu un alt scop.

Potrivirea unor caractere daca alte caractere sunt sau nu prezente

Expresiile regulate ne ofera posibilitatea sa potrivim diferite caractere din textul tinta daca alte caractere sunt prezente sau nu. Aceasta tehnica mai poarta denumirea si de lookaround assertions. Lookaround assertions este impartit in doua categorii cu denumirea generica de pozitiv si negativ cu referire directa la caracterele prezente si la caracterele care nu sunt prezente, in aceasta ordine. Lookaround assertions are rolul de a potrivi un set de caractere daca alte caractere sunt prezente iar aceste caractere nu vor face parte din ce a potrivit. Lookaround assertions are lungimea de zero caractere.

Potrivirea unor caractere daca alte caractere sunt prezente

Sintaxa pozitiv lookaround assertions

Sintaxa pentru pozitiv lookaround assertions este una foarte simpla si asemanatoare cu non-capturing group iar diferenta este ca in locul caracterului doua puncte vom avea semnul egal pentru pozitiv urmat apoi de caracterul dupa care vom face referinta sau restul de expresie regulata.

/\w(?=,)/ → va potrivi un caracter litera, cifra sau underscore care are imediat langa el o virgula

Potrivirea unor caractere daca alte caractere nu sunt prezente

Sintaxa negativ lookaround assertions

Sintaxa pentru negativ lookaround assertions este aproape identica cu pozitiv lookaround assertions iar diferenta este ca in locul caracterului egal vom avea semnul mirarii.

/\w(?!,)/ → va potrivi un caracter litera, cifra sau underscore care nu are imediat langa el o virgula

Important la lookaround assertions

Lookaround assertions ne permite sa facem mai multe decat v-am aratat pana acum. Putem sa facem mai multe teste pe acelasi set de caractere si sa vedem daca un anumit set de cifre intruneste diferite formate. Sa presupunem ca avem urmatoarele randuri cu numere de telefon si vrem sa potrivim un numar de telefon sau mai multe daca intruneste toate cerintele noastre.

  • 555-782-5699
  • 555-231-3210
  • 555-450-1234

Sa zicem ca vrem sa potrivim un numar ce contine cifrele de la 0 la 5 separate de caracterul minus si este in formatul de trei cifre pe primele seturi si la sfarsit un set format din patru cifre. Cu urmatoare expresie regulata vom potrivi al doilea si al treilea numar.

/(?=^[0-5\-]+$)\d{3}-\d{3}-\d{4}/m

Practic i-am spus interpretorului de expresie regulata sa caute in modul multiline un set de cifre care de la inceput si pana la sfarsit va trebui sa contina cifrele de la zero la cinci, separate de caracterul minus si in formatul de trei cifre urmate de caracterul minus, apoi alte trei cifre urmate si acestea de caracterul minus si in final un set de patru cifre.

Acum este timpul sa adaugam inca un nivel in expresia regulata si vrem sa testam daca acel numar se termina cu 3210 pentru ca vrem sa potrivim numarul din mijloc. Urmatoarea expresie regulata este mai mult decat intuitiva si va potrivi numarul de telefon din mijloc.

/(?=^[0-5\-]+$)(?=.+3210)\d{3}-\d{3}-\d{4}/m

Ce am vrut sa va arat cu aceste exemple a fost sa va arat ca folosind lookaround assertions puteti sa testati in mai multe feluri in aceasi expresie regulata un set de caractere si prin aceasta modalitate sa scrieti mai putin cod dar mult mai inteligent.

Desi nu v-am spus pana acum, lookaround assertions a cautat daca diferite caractere din textul tinta sunt prezente dupa caracterele pe care vrem sa le potrivim iar aceasta tehnica poarta denumirea de lookahead assertions. Exista si opusul acesteia si poarta denumirea de lookbehind assertions si din pacate nu este suportata de limbajul JavaScript, Ruby 1.8 si UNIX dar este suportat de limbajele .NET, Java, Perl, PHP, Python si de la Ruby 1.9.

Lookbehind assertions functioneaza aproape identic cu lookahead assertion iar diferenta este data de sintaxa (ce are intre caracterul semnul intrebarii si egal sau semnul mirarii caracterul mai mic sau mai mare →<←) si de diferite limbaje care accepta sau nu rolul caracterelor →*← si →+←.

Cateva exemple de tinut minte

La sfarsit va dau cateva exemple pe care este bine sa le retineti pentru ca va pot fi de mare folos iar scrierea unei expresii regulate cu care sa iti faci treaba cat mai inteligent va face diferenta intre un programator bun si unul foarte bun.

  • /(Java)(?!.+\1)/
  • va potrivi ultima prezenta a cuvantului Java dintr-un text
  • /<(em|strong)>.*?<\/\1>/
  • va potrivi o eticheta html din grup cu tot continutul din interior - non lacom
  • ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
  • va potrivi orice adresa IP de la 0.0.0.0 la 255.255.255.255, acesta fiind si intervalul de adrese IP