Expresii regulate  


Cãutare


Siteuri recomandate

  • ABC Domenii Pachete de gazduire pentru siteuri personale si bloguri.
  • AutoIt Script Curs AutoIt in limba romana.
  • CHML Web Services Servere dedicate si servere virtuale private.
  • Hostvision Gazduire siteuri web si inregistrare domenii
  • IPFind.eu IPFind.eu – Free IP address finder and DNS troubleshooter
  • LAMP Platforma open source de gazduire a site-urilor web.
  • NetHelp Intrebari tehnice si raspunsuri de calitate pentru intrebari tehnice.
  • SkullBox Comunitate online pentru pasionatii de IT.
  • WordPress Admin Tutoriale de utilizare si administrare a blogurilor WordPress.

Caracterul punct in PCRE

Punctul este un meta-caracter care indică aproape orice alt caracter. Prin cuvântul aproape trebuie să avem în vedere şi caracterele Unicode atunci când funcţiile pentru lucrul cu Unicode sunt compilate în PCRE. Ideea este că prin caracter, în varianta Unicode se înţelege un aşa numit code point. Un caracter Unicode poate să conţină mai multe codepointuri, spre exemplu caractere cu umlaut din germană. În acel moment punctul nu identifică chiar orice caracter şi în loc să-şi facă treaba în mod corect va identifica altceva. Bineînţeles că la prima vedere un caracter cu umlaut poate părea un singur caracter dar nu este neapărat aşa şi în variantă practică. Dacă PCRE-ul este compilat şi cu Unicode atunci putem să folosim un alt operator şi anume \X pentru a descoperi caracterele. Acest operator găseşte orice caracter indiferent dacă are un code point sau mai multe code pointuri. Trebuie să fim atenţi doar la noanţă şi la ceea ce înseamnă un caracter cu adevărat.

Totuşi, dacă ne rezumăm doar la ASCII punctul ne va fi mai mult decât de ajutor însă folosit cu chibzuinţă. Şi nu numai, punctul este unul dintre cele mai folosite meta-caractere, tocmai pentru faptul că identifică aproape orice caracter şi la prima vedere pare să rezolve rapid toate problemele unui programator. Bineînţeles că pe măsură ce trebuiesc filtrate caracterele primite sau căutate punctul nu mai este o soluţie viabilă. Am scris aproape orice caracter căci punctul nu indică spre caracterele de newline (\n). Mai pe scurt, punctul este şi un meta-caracter cât şi o clasă negată şi anume: [^\n] (asta este pentru UNIX). Dacă lucrăm pe Windows observăm că punctul nu indică nici spre \r deci acolo punctul este o clasă negată la [^\r\n]. Motivul pentru care punctul nu indică şi spre aceste caractere (\n şi/sau \r, după caz) este că primele motoare pentru expresii regulate lucrau linie cu linie. Lucrând linie cu linie era imposibil să se întâlnească un newline. Deci treaba este din motive istorice. Ţinem cont totuşi că motoarele moderne de expresii regulate nu mai lucrează pe un singur rând, ba din contră pe şiruri de text enorme sau fişiere mari. De aceea în astfel de motoare moderne se poate indica ca punctul să indice şi \n. În Perl, modul în care newline-urile sunt indicate de punct se numeşte modul „o singură linie” (single-line, în engleză). Putem activa după caz modul single-line sau modul multi-line fără să apară probleme la interpretarea expresiei regulate. În cazul în care activăm modul single-line meta-caracterul punct din expresia regulată va indica şi spre newline \n, în cazul în care activăm multi-line, metacaracterul . nu va indica şi newline. În motorul RegEx de la JavaScript şi VBScript nu avem opţiunea pentru a identifica sfârşiturile de linie, deci posibilitatea începutului altei linii. În aceste două limbaje pentru a identifica orice caracter putem să folosim o clasă ca în exemplul următor: [\s\S]. Asta înseamnă că această clasă identifică orice caracter care este spaţiu alb sau nu este spaţiu alb, deci orice caracter. Asta include (spre deosebire de punct pe modul single-line) şi identificarea de sfârşituri de linie.

Prin simplul fapt că punctul permite să identificăm orice caracter ne face să fim leneşi, probabil. Dacă suntem la început cu expresiile regulate şi ştim că punctul indentifică orice caracter vom fi tentaţi să adăugăm punct în mai multe locuri decât este nevoie. Să luăm un exemplu în care punctul ar putea fi folosit în mod greşit: spre exemplu vrem să delimităm două cuvinte prin slash (/) sau cratima (-). Nu este deajuns să punem punct între ele programator.bun caci acesta va indica şi spre programatorabun, ceea ce nu vrem. Caracterul a nu delimitează vizual cele două cuvinte. În locul punctului, pe care am fi tentaţi să-l folosim ştiind că indică spre orice caracter, putem folosi o clasă de caractere în care includem caracterele de delimitare prestabilite de noi. Depinde ce vrem să obţinem cu un anumit RegEx şi contextul în care-l folosim. Dacă, spre exemplu, dorim să delimităm cuvintele programator şi bun cu caracterul a sau orice alt caracter, atunci putem să folosim şi meta-caracterul punct în şablon. Dacă vrem să fim mai precişi şi să indicăm anumite caractere pentru delimitare atunci putem folosi clase de caractere. Să urmărim funcţionarea motorului RegEx pe următorul şablon cu următorul şir de caractere de căutat: şablon .+ şi şirul programare. Acesta nu va returna niciodată gol căci operatorul + trebuie facă ca respectivul caracter interpretat de punct să apară cel puţin o dată (nu este neapărat ca acel caracter să apară consecutiv, punctul poate interpreta orice caracter şi un răspuns valid poate fi următorul ab1). Asta dacă nu băgăm în seamă treaba cu Unicode descrisă mai devreme. Trebuie să fim atenţi şi la faptul că operatorul punct este unul lacom alături de ? sau + şi nu se va opri la primul rezultat valabil şi va mai face backtrackinguri să caute poate, poate mai există şi alte rezultate la fel de valabile, caz în care se va rămâne la ultimul rezultat valabil şi restul vor dispărea.

Încă un exemplu în care am fi tentaţi să folosim punctul este următorul: să presupunem că vrem să căutăm toate cuvintele care se află între ghilimele dintr-o frază. Se dă fraza: Un „programator” bun este un programator „bun”. Pare uşor şi un începător în expresii regulate ar putea scrie un şablon de genul: .* (putem avea orice număr de orice caracter cât şi caractere întercalate). La prima vedere pare bine, însă expresia „programator” bun este un programator „bun” va fi returnată. Dacă disecăm puţin şablonul vom vedea că tocmai această expresie este cea optimă, nu cele două cuvinte puse între ghilimele pe care am fi vrut să le scoatem în evidenţă. Motivul este că * este greedy (lacom). Ce înseamnă acest lucru? Procesul va fi repetat ori de câte ori este posibil. Nu este deajuns că a găsit deja primul cuvânt între ghilimele sau al doilea. Motorul de expresii regulate va repeta procesul să „vadă” dacă există şi un al treilea cuvânt (expresie) între ghilimele. Şi chiar dacă este o expresie, această există şi ea va fi returnată.