Expresii regulate orice alt caracter decât cel dat. Cheat sheet pentru expresia regulată

Modificatori

Simbolul minus (-) plasat lângă un modificator (cu excepția lui U) creează negația acestuia.

Personaje speciale

AnalogicDescriere
() submodel, expresie imbricată
wildcard
(a,b) numărul de apariții de la „a” la „b”
| logic „sau”, în cazul utilizării alternative cu un singur caracter
\ scăpa de caracter special
. orice caracter, cu excepția avansului de linie
\d cifră zecimală
\D[^\d]orice caracter, altul decât o cifră zecimală
\f sfârşit (încălcare de pagină)
\n traducere de linie
\pL literă în codificare UTF-8 când utilizați modificatorul u
\r retur transport
\s[\t\v\r\n\f]caracter spațial
\S[^\s]orice simbol, cu excepția celui care clipește
\t intabulare
\w orice număr, literă sau subliniere
\W[^\w]orice caracter în afară de un număr, literă sau liniuță de subliniere
\v filă verticală

Caractere speciale dintr-o clasă de caractere

Poziție în cadrul unei linii

ExempluCorespondenţăDescriere
^ ^aA aa aaaînceput de linie
$ a$aaa aa A sfârşitul rândului
\A\AaA aa aaa
aaa aaa
începutul textului
\za\zaaa aaa
aaa aa A
sfârşitul textului
\ba\b
\ba
aa A aa A
A aa A aa
graniță de cuvânt, enunț: caracterul anterior este verbal, dar următorul nu, sau invers
\B\Ba\BA A a a A Anici o limită de cuvinte
\G\Gaaaa aaaCăutarea anterioară cu succes, căutarea s-a oprit la poziția a 4-a - unde a nu a fost găsit
Descărcați în PDF, PNG.

Ancore

Ancorele din expresiile regulate indică începutul sau sfârșitul a ceva. De exemplu, rânduri sau cuvinte. Ele sunt reprezentate prin anumite simboluri. De exemplu, un model care se potrivește cu un șir care începe cu un număr ar arăta astfel:

Aici caracterul ^ indică începutul liniei. Fără el, modelul s-ar potrivi cu orice șir care conține o cifră.

Clasele de caractere

Clasele de caractere din expresiile regulate se potrivesc simultan cu un anumit set de caractere. De exemplu, \d se potrivește cu orice număr de la 0 la 9 inclusiv, \w se potrivește cu litere și cifre și \W se potrivește cu toate caracterele, altele decât literele și cifrele. Modelul de identificare a literelor, numerelor și spațiului arată astfel:

POSIX

POSIX este o adăugare relativ nouă la familia expresiilor regulate. Ideea, ca și în cazul claselor de caractere, este de a folosi comenzi rapide care reprezintă un anumit grup de caractere.

Declarații

Aproape toată lumea are probleme în a înțelege afirmațiile la început, dar pe măsură ce vă familiarizați cu ele, vă veți descoperi că le utilizați destul de des. Afirmațiile oferă o modalitate de a spune: „Vreau să găsesc fiecare cuvânt din acest document care include litera „q” și nu este urmat de „werty”.

[^\s]*q(?!werty)[^\s]*

Codul de mai sus începe prin căutarea altor caractere decât spațiu ([^\s]*) urmate de q . Analizatorul ajunge apoi la o afirmație orientată spre viitor. Acest lucru face automat elementul precedent (caracter, grup sau clasă de caractere) condiționat - se va potrivi cu modelul numai dacă afirmația este adevărată. În cazul nostru, afirmația este negativă (?!), adică va fi adevărată dacă nu se găsește ceea ce se caută în ea.

Deci, analizatorul verifică următoarele câteva caractere cu modelul propus (werty). Dacă sunt găsite, atunci afirmația este falsă, ceea ce înseamnă că caracterul q va fi „ignorat”, adică nu se va potrivi cu modelul. Dacă nu se găsește werty, atunci afirmația este adevărată și totul este în ordine cu q. Apoi căutarea continuă pentru orice alt caracter decât spațiu ([^\s]*).

Cuantificatori

Cuantificatorii vă permit să definiți o parte a unui model care trebuie repetat de mai multe ori la rând. De exemplu, dacă doriți să aflați dacă un document conține un șir de 10 până la 20 (inclusiv) de litere „a”, atunci puteți utiliza acest model:

A(10,20)

În mod implicit, cuantificatorii sunt „lacomi”. Prin urmare, cuantificatorul +, adică „de una sau mai multe ori”, va corespunde valorii maxime posibile. Uneori, acest lucru cauzează probleme, caz în care puteți spune cuantificatorului să nu mai fie lacom (deveni „leneș”) folosind un modificator special. Uită-te la acest cod:

".*"

Acest model se potrivește cu textul cuprins între ghilimele duble. Cu toate acestea, linia sursă ar putea fi cam așa:

Salut Lume

Șablonul de mai sus va găsi următorul subșir în această linie:

"helloworld.htm" title="Buna ziua lume" !}

S-a dovedit a fi prea lacom, luând cea mai mare bucată de text pe care o putea.

".*?"

Acest model se potrivește și cu orice caractere cuprinse între ghilimele duble. Dar versiunea leneșă (observați modificatorul?) caută cea mai mică apariție posibilă și, prin urmare, va găsi fiecare subșir cu ghilimele duble individual:

„helloworld.htm” „Hello World”

Evadarea în expresii regulate

Expresiile regulate folosesc anumite caractere pentru a reprezenta diferite părți ale unui model. Cu toate acestea, apare o problemă dacă trebuie să găsiți unul dintre aceste caractere într-un șir, la fel ca un caracter obișnuit. Un punct, de exemplu, într-o expresie regulată înseamnă „orice caracter, altul decât o întrerupere de linie”. Dacă trebuie să găsiți un punct într-un șir, nu puteți utiliza doar „ . » ca șablon - acest lucru va duce la găsirea aproape orice. Deci, trebuie să spuneți analizorului că acest punct ar trebui considerat un punct obișnuit și nu „orice caracter”. Acest lucru se face folosind un semn de evacuare.

Un caracter de escape care precede un caracter, cum ar fi un punct, face ca analizatorul să-și ignore funcția și să-l trateze ca pe un caracter normal. Există mai multe caractere care necesită o astfel de evadare în majoritatea șabloanelor și limbilor. Le puteți găsi în colțul din dreapta jos al foii de cheat ("Meta Simboluri").

Modelul pentru găsirea unui punct este:

\.

Alte caractere speciale din expresiile regulate se potrivesc cu elemente neobișnuite din text. De exemplu, rupturile de linie și tabulațiile pot fi tastate pe tastatură, dar sunt susceptibile de a încurca limbajele de programare. Caracterul de evacuare este folosit aici pentru a-i spune analizorului să trateze următorul caracter ca un caracter special, mai degrabă decât o literă sau un număr obișnuit.

Caractere speciale de evadare în expresiile regulate

Înlocuirea șirurilor

Substituția șirurilor este descrisă în detaliu în paragraful următor, „Grupuri și intervale”, dar existența grupurilor „pasive” ar trebui menționată aici. Acestea sunt grupuri care sunt ignorate în timpul înlocuirii, ceea ce este foarte util dacă doriți să utilizați o condiție „sau” într-un model, dar nu doriți ca acel grup să ia parte la înlocuire.

Grupuri și intervale

Grupurile și intervalele sunt foarte, foarte utile. Probabil că este mai ușor să începeți cu intervale. Acestea vă permit să specificați un set de caractere adecvate. De exemplu, pentru a verifica dacă un șir conține cifre hexazecimale (de la 0 la 9 și de la A la F), ați folosi următorul interval:

Pentru a verifica contrariul, utilizați un interval negativ, care în cazul nostru se potrivește oricărui caracter, cu excepția numerelor de la 0 la 9 și a literelor de la A la F:

[^A-Fa-f0-9]

Grupurile sunt folosite cel mai adesea atunci când este necesară o condiție „sau” într-un model; când trebuie să faceți referire la o parte a unui șablon dintr-o altă parte a acestuia; și, de asemenea, atunci când înlocuiți șiruri.

Utilizarea „sau” este foarte simplă: următorul model caută „ab” sau „bc”:

Dacă într-o expresie obișnuită este necesar să se facă referire la unul dintre grupurile anterioare, ar trebui să folosiți \n , unde în loc de n înlocuiți numărul grupului dorit. Poate doriți un model care să se potrivească cu literele „aaa” sau „bbb” urmate de un număr și apoi de aceleași trei litere. Acest model este implementat folosind grupuri:

(aaa|bbb)+\1

Prima parte a modelului caută „aaa” sau „bbb”, combinând literele găsite într-un grup. Aceasta este urmată de o căutare pentru una sau mai multe cifre (+) și, în final, \1. Ultima parte a modelului face referire la primul grup și caută același lucru. Caută o potrivire cu textul deja găsit de prima parte a modelului, nu o potrivire cu acesta. Deci „aaa123bbb” nu va satisface modelul de mai sus, deoarece \1 va căuta „aaa” după număr.

Unul dintre cele mai utile instrumente în expresiile regulate este înlocuirea șirurilor. Când înlocuiți text, puteți face referire la grupul găsit folosind $n . Să presupunem că doriți să evidențiați toate cuvintele „dorință” din text cu caractere aldine. Pentru a face acest lucru, ar trebui să utilizați o funcție de înlocuire a expresiei regulate, care ar putea arăta astfel:

Înlocuiește (model, înlocuire, subiect)

Primul parametru va fi cam așa (s-ar putea să aveți nevoie de câteva caractere suplimentare pentru această funcție anume):

([^A-Za-z0-9])(dorință)([^A-Za-z0-9])

Va găsi orice apariție a cuvântului „dorință” împreună cu caracterele anterioare și următoare, atâta timp cât acestea nu sunt litere sau cifre. Atunci înlocuirea ta ar putea fi așa:

$1$2$3

Acesta va înlocui întregul șir găsit folosind modelul. Începem să înlocuim cu primul caracter găsit (care nu este o literă sau un număr), marcându-l $1 . Fără aceasta, am elimina pur și simplu acest caracter din text. Același lucru este valabil și pentru sfârșitul înlocuirii ($3). La mijloc am adăugat o etichetă HTML pentru bold (desigur, puteți folosi CSS sau ), alocandu-le al doilea grup găsit folosind șablonul ($2).

Ți-ai dorit vreodată să înveți regexp? Acest mic ghid vă va ajuta să le înțelegeți în 6 pași, iar abundența de exemple vă va ajuta să consolidați materialul.

Ce este regexp?

Regexp este un grup de caractere sau caractere care este folosit pentru a căuta un anumit model de text.

O expresie regulată este un model care se potrivește cu un șir de subiect de la stânga la dreapta. Expresia „expresie regulată” nu este folosită atât de larg; în schimb, „regex” și „regexp” sunt de obicei folosite. Expresia regulată este folosită pentru a înlocui textul dintr-un șir, pentru a valida un formular, pentru a extrage un subșir dintr-un șir pe baza potrivirii modelului etc.

Să presupunem că construiți o aplicație și doriți să definiți reguli pentru modul în care utilizatorii își aleg numele. De exemplu, dorim să conțină litere, cifre, litere de subliniere și cratime. De asemenea, am dori să limităm numărul de caractere din numele de utilizator, astfel încât să nu arate urât. Prin urmare, vom folosi următoarea expresie regulată pentru a verifica:

Această expresie acceptă șirurile john_doe, jo-hn_doe și john12_as. Cu toate acestea, numele de utilizator Jo nu se va potrivi cu această expresie deoarece conține o literă mare și este, de asemenea, prea scurt.

1. Potriviri de bază

O expresie regulată este doar un model de caractere pe care îl folosim pentru a efectua o căutare în text. De exemplu, expresia regulată înseamnă litera t urmată de litera h urmată de litera e.

„the” => Pisica grasă stătea pe cel mat.

Expresia regulată 123 se potrivește cu șirul 123. O expresie regulată se potrivește cu un șir de intrare comparând fiecare caracter din expresia regulă cu fiecare caracter din șirul de intrare. Expresia regulată și șirul de intrare sunt comparate caracter cu caracter. În mod obișnuit, expresia regex ține seama de majuscule și minuscule, deci The nu se potrivește cu șirul .

„The” => The pisica grasă stătea pe saltea.

2. Metacaracterele

Metacaracterele servesc ca elemente de bază ale expresiilor regulate. Ele nu sunt independente și sunt de obicei interpretate într-un fel sau altul. Unele metacaractere au o semnificație specială și, prin urmare, sunt plasate între paranteze drepte. Metacaracterele:

Metacaracterele Descriere
. Orice caracter unic, excluzând noua linie.
Căutați un set de caractere plasate în paranteze.
[^ ] Clasă de caractere negate. Se potrivește cu orice caracter care nu este cuprins între paranteze drepte
* 0 sau mai multe repetări ale caracterului precedent.
+ 1 sau mai multe repetări ale caracterului precedent.
? Face caracterul precedent opțional.
(n,m) Returnează cel puțin „n” dar nu mai mult de „m” repetări ale caracterului precedent.
(xyz) Găsește un grup de caractere într-o ordine strict specificată.
| Separă opțiunile valide.
\ Exclude următorul caracter. Vă permite să căutați simboluri de serviciu () (). * + ? ^$\|
^ Găsește începutul șirului introdus.
$ Găsește sfârșitul șirului introdus.

2.1 Punct

. este cel mai simplu exemplu de metacaracter. Metacaracter. se potrivește cu orice caracter. De exemplu, expresia regulată .ar înseamnă: orice caracter urmat de litera a urmată de litera r.

".ar" => The par. auto ked în gar vârstă.

2.2 Spațierea dintre caractere

Un interval sau un set de caractere se mai numește și clasă de caractere. Parantezele pătrate sunt folosite pentru a-l desemna. Pentru a indica o serie de caractere dintr-o clasă, trebuie să utilizați o liniuță. Ordinea unui număr de caractere dintr-un set nu este importantă. Deci, de exemplu, expresia regulată pe care o înseamnă: T sau t urmată de litera h urmată de litera e.

„el” => The masina parcata in cel garaj.

Este demn de remarcat faptul că un punct plasat între paranteze pătrate înseamnă un punct și nimic altceva. Astfel, expresia regulată ar[.] înseamnă caracterul mic a urmat de litera r urmată de un punct. .

„ar [.]” => Un garaj este un loc bun pentru a parca un c ar.

2.2.1 Negarea setului de caractere

În mod normal, caracterul ^ reprezintă începutul unei linii, dar când este între paranteze drepte, toate caracterele care vin după el sunt excluse din model. De exemplu, expresia [^c]ar va ajuta la găsirea tuturor caracterelor, cu excepția lui c urmat de a și r.

"[^c]ar" => Mașina alin ked în gar vârstă.

2.3 Repetări

Următoarele meta caractere sunt + , * sau ? sunt folosite pentru a indica numărul permis de repetări ale unui submodel. Rolul lor depinde de cazul specific.

2.3.1 Asterisc

Acest simbol vă va ajuta să găsiți una sau mai multe copii ale unui simbol. Expresia regulată a* înseamnă 0 sau mai multe repetări ale caracterului a. Dar dacă acest caracter apare după un set sau o clasă de caractere, atunci vor fi găsite repetări ale întregului set. De exemplu, expresia * înseamnă orice număr de aceste caractere dintr-un șir.

"*" => Mașina a parcat în garaj #21.

Simbolul poate fi folosit și împreună cu un metacaracter. pentru a selecta un șir din orice caracter.* .

De asemenea, puteți utiliza un asterisc cu un caracter de spațiu \s pentru a se potrivi cu un șir de spații. De exemplu, expresia \s*cat\s ar însemna 0 sau mai multe spații, urmate de c, urmate de a și t, urmate de 0 sau mai multe spații.

"\s*cat\s*" => Grăsimea pisică a stat pe con pisică enatie.

2.3.2 Plus

Potrivește una sau mai multe repetări ale caracterului anterior. De exemplu, expresia regulată c.+t înseamnă: o literă mică c urmată de cel puțin un caracter urmat de un caracter mic t . Este necesar să lămurim că litera t trebuie să fie ultimul t din propoziție.

"c.+t" => Grăsimea pisica a stat pe saltea.

2.3.3. Semnul întrebării

Există un metacaracter în expresia regulată? face ca caracterul precedent să fie opțional. Acest simbol corespunde absenței complete sau unei instanțe a simbolului anterior. De exemplu, expresia regulată [T]?he înseamnă: o literă majusculă opțională T urmată de un h minuscul urmat de un e minuscul.
„[T]el” => The masina este parcata in garaj.
Testarea expresiei

„[T]?el” => The masina este parcata in t el garaj.

2.4 Paranteze

Parantezele din expresia regulată, numite și cuantificatori, sunt folosite pentru a specifica de câte ori un caracter sau un grup de caractere poate fi repetat. De exemplu, expresia regulată (2,3) înseamnă că numărul permis de cifre trebuie să fie de cel puțin două cifre, dar nu mai mult de 3 (caractere cuprinse între 0 și 9).

"(2,3)" => Numărul a fost 9. 999 7 dar l-am rotunjit la 10 .0.

Putem elimina al doilea număr. De exemplu, expresia (2,) înseamnă 2 sau mai multe cifre. Dacă eliminăm și virgula, atunci expresia (3) va găsi doar 3 cifre, nici mai puțin, nici mai mult.

"(2,)" => Numărul a fost 9. 9997 dar am rotunjit-o la 10 .0.

„(3)” => Numărul a fost 9. 999 7, dar l-am rotunjit la 10,0.

2.5 Grup de caractere

Un grup de caractere este un grup de submodele care este scris între paranteze (...) . După cum am menționat mai devreme, dacă puneți un cuantificator după un caracter într-o expresie regulată, acesta va repeta caracterul anterior. Dar dacă punem un cuantificator după un grup de caractere, acesta va repeta pur și simplu întregul grup. De exemplu, expresia regulată (ab)* se potrivește cu zero sau mai multe apariții ale caracterului „ab”. Putem folosi și | — metacaracter alternant în cadrul unui grup de caractere. De exemplu, expresia regulată (c|g|p)ar înseamnă: un caracter mic c , g sau p urmat de un caracter urmat de r .

"(c|g|p)ar" => The mașină este alin ked în gar vârstă.

2.6 Transfer

În regexp există o bară verticală | folosit pentru a defini o enumerare. O enumerare este ceva ca o condiție între mai multe expresii. Ai putea crede că setul de caractere și enumerarea funcționează la fel, dar acest lucru nu este deloc adevărat, există o diferență uriașă între ele. O enumerare operează la nivel de expresie, în timp ce un set de caractere operează la nivel de caractere. De exemplu, expresia regulată (T|t)he|car înseamnă: T sau t urmat de o literă h , urmată de o literă e sau c mică , urmată de a și r .

„(T|t)he|car” => Mașina este parcat in cel garaj.

2.7 Excluderea caracterelor speciale

Bara oblică inversă \ este folosită în expresia regulată pentru a scăpa de caracterul care îl urmează. Acest lucru ne permite să specificăm un caracter ca caracter de potrivire, inclusiv pe cele rezervate ( ) / \ + * . $^| ? . Pentru a utiliza un caracter special ca potrivire, trebuie să-l precedați cu \.

De exemplu, o expresie regulată. folosit pentru a găsi orice caracter. Expresia regulată (f|c|m)at\.? înseamnă un f, c sau m minuscule, urmat de un a, urmat de un t urmat de un caracter suplimentar. .

"(f|c|m)at\.?" =>The pisica grasa a stat pe mat.

2.8 Ancore - Legături

În regexp, folosim ancore pentru a verifica dacă caracterul potrivit este primul sau ultimul caracter al șirului de intrare. Există două tipuri de ancoră: primul este ^, care verifică dacă caracterul potrivit este primul caracter introdus, iar al doilea este semnul dolar, care verifică dacă caracterul potrivit este ultimul caracter al șirului introdus.

2.8.1. Semn de omisiune

Caracterul ^ este folosit în expresia regulă pentru a verifica dacă caracterul potrivit este primul caracter din șirul de intrare. Dacă aplicăm următoarea expresie regulată ^a (verificați dacă a este primul caracter) pe șirul de intrare abc , atunci va fi egal cu a . Dar dacă aplicăm expresia regulată ^b aceluiași șir, atunci nu va returna nimic deoarece în șirul de intrare abc caracterul „b” nu este primul. Să ne uităm la o altă expresie regulată ^(T|t)he care înseamnă: T sau t este caracterul de început al șirului de intrare urmat de caracterul minuscul h și apoi e .

„(T|t)he” => The masina este parcata in cel garaj.

„^(T|t)el” => The masina este parcata in garaj.

2.8.2 dolari

Semnul dolar este folosit pentru a verifica dacă caracterul dintr-o expresie este ultimul caracter din șirul introdus. De exemplu (la\.)$ înseamnă literă a urmată de t urmată de a . , care trebuie să încheie linia.

"(la\.)" => Grăsimea c la. s la. pe ei la.

"(la\.)$" => Pisica grasă. sat. pe ei la.
Testarea expresiei

3. Abrevieri pentru simboluri

Regexp vă permite să utilizați abrevieri pentru anumite seturi de caractere, ceea ce face ca lucrul cu acestea să fie mai confortabil. Deci următoarele abrevieri sunt folosite aici:

4. Privire în jur Verificarea poziției

Privire în urmă și înainte (numite și privire în jur) sunt anumite tipuri de grupuri care nu captează (sunt folosite pentru căutare, dar nu fac parte din ele însele). Lookaheads sunt folosite atunci când avem o condiție ca acest model să fie precedat sau urmat de un alt model. De exemplu, dorim să obținem toate numerele precedate de un caracter $ din șirul de intrare $4,44 și $10,88 . Vom folosi expresia regulată (?<=\$)* , которое означает: получить все числа, содержащие. и которым предшествует символ $ . Ниже приведены lookarounds, что используются в регулярных выражениях:

4.1 Perspectivă pozitivă

O anticipare pozitivă înseamnă că această parte a expresiei trebuie să urmeze expresia anterioară. Valoarea returnată conține textul care se potrivește cu prima parte a expresiei. Pentru a defini o anticipare pozitivă, utilizați paranteze. În interiorul lor sunt plasate un semn de întrebare și un semn egal: (?=...) . Expresia în sine se scrie după =. De exemplu, expresia (T|t)he(?=\sfat) este un T majuscul sau mic urmat de h și e . În paranteze definim un lookahead pozitiv, care îi spune motorului de expresii regulate să caute The sau the urmat de fat .

„(T|t)he(?=\sfat)” => The pisica grasă stătea pe saltea.

4.2 Perspectivă negativă

Lookahead negativ este folosit atunci când trebuie să obținem toate potrivirile într-un șir care nu este urmat de un model specific. Un lookahead negativ este definit la fel ca unul pozitiv, singura diferență este că în loc de semn egal folosim un semn negativ! . Astfel, expresia noastră îmbracă următoarea formă: (?!...) . Acum luați în considerare (T|t)he(?!\sfat) , ceea ce înseamnă: obțineți tot The sau the din șirul de intrare care nu este urmat de cuvântul fat precedat de un caracter spațiu.

"(T|t)he(?!\sfat)" => Pisica grasă stătea cel mat.

4.3 Privire pozitivă în urmă

O privire în urmă pozitivă este utilizată pentru a prelua toate potrivirile care sunt precedate de un anumit model. O privire pozitivă în urmă se notează după cum urmează: (?<=...) . Например, регулярное выражение (?<=(T|t)he\s)(fat|mat) означает получить все fat или mat из строки ввода, которые идут после слова The или the .

„(? The gras pisica stătea pe mat.

4.4 Privire negativă în urmă

Lookbehind negativ este folosit pentru a obține toate potrivirile care nu sunt precedate de un anumit model. O privire negativă în urmă este indicată de expresia (?

5. Steaguri

Flag-urile sunt deseori numite modificatori, deoarece pot schimba rezultatul expresiei regulate. Steagurile de mai jos sunt parte integrantă și pot fi utilizate în orice ordine sau combinație de expresii regulate.

5.1 Nu ține seama de majuscule și minuscule

Modificatorul i este folosit pentru a căuta potriviri care nu țin cont de majuscule. De exemplu, /The/gi înseamnă un T mare urmat de un h și un e. Și la sfârșitul expresiei există i , datorită căruia puteți ignora majuscule. g este folosit pentru a găsi un model în întregul șir de intrare.
„The” => The pisica grasă stătea pe saltea.
Testarea expresiei

„/The/gi” => The pisica grasă stătea pe cel mat.

5.2 Căutare globală

Modificatorul este folosit pentru a efectua o căutare globală a unui model (căutarea va continua după prima potrivire). De exemplu, expresia regulată /.(at)/g se potrivește cu orice caracter, altul decât o nouă linie urmată de litere mici a și apoi a t . Deoarece am folosit indicatorul g la sfârșitul expresiei regulate, acum va găsi toate potrivirile în șirul de intrare, nu doar primul (care este standardul).

"/.(at)/" => The gras pisica a stat pe saltea.

„/.(at)/g” => The pisica grasa sat pe mat.

5.3 Căutare pe mai multe linii

Modificatorul m este necesar pentru a efectua o căutare pe mai multe linii. După cum sa menționat mai devreme, ancorele (^, $) sunt folosite pentru a verifica dacă un model este începutul sau sfârșitul unui șir. Dar dacă vrem ca legările să funcționeze pe fiecare linie, trebuie să folosim steag-ul m. De exemplu, expresia regulată /at(.)?$/gm înseamnă: un caracter mic a urmat de un t și orice altceva decât o nouă linie. Și datorită steagului m, acest motor de expresii regulate se potrivește cu modelul de la sfârșitul fiecărei linii a șirului.

"/.at(.)?$/" => Grăsimea
cat sat
pe mat.

"/.at(.)?$/gm" => The gras
pisică sat

O introducere ușoară și distractivă în teoria expresiei regulate de la dezvoltatorul web Josh Hawkins, Regex acoperă toate elementele de bază pe care un începător trebuie să le cunoască.

Ați lucrat vreodată cu corzi? Da, da, cu acele „matrice de caractere” pe care le cunoaștem și le iubim cu toții. Dacă ați programat în altceva decât în ​​C pur, este sigur să presupuneți că ați făcut, și de mai multe ori. Dar dacă ai de-a face cu o mulțime de șiruri? Sau cu șiruri care nu au fost generate de programul tău? De exemplu, citiți un e-mail, analizați argumentele liniei de comandă sau citiți instrucțiuni scrise de oameni și aveți nevoie de o modalitate mai structurată de a gestiona totul.

Desigur, puteți repeta fiecare cuvânt sau caracter din toate rândurile. Și un astfel de cod va fi probabil destul de ușor de înțeles. Dar, în aplicațiile la scară largă, acest lucru poate fi inutil de greoi și poate consuma prea mult resurse.

Introducere. Expresie uzuala

Fără a intra în jungla informaticii profunde, să definim o expresie regulată.

  • Expresiile regulate sunt reguli care descriu un limbaj formal.
  • Expresiile regulate sunt un tip de limbaj formal care poate fi procesat de o mașină de stări.

Există multe alte definiții ale expresiilor regulate, așa că dacă cele de mai sus nu sunt suficiente pentru a vă face fericit, puteți petrece câteva minute Google.

Introducere. Regex

Acum s-ar putea să ajungem la punctul în care este timpul să ne sperii (dacă nu ați făcut-o deja). Ne vom uita la diferențele dintre ceea ce este inclus în conceptul de expresii regulate în limbajele de programare și ceea ce este inclus în informatica fundamentală.

  • Expresiile regulate din punctul de vedere al informaticii sunt reguli care explică un limbaj formal.
  • Expresiile regulate din punctul de vedere al limbajelor de programare sunt o gramatică care exprimă, într-o măsură mai mare, unele limbaj sensibil la context.

Limbile sensibile la context sunt semnificativ mai complexe și mai puternice, așa că de acum încolo vom fi de acord să numim expresiile regulate din limbajul de programare termeni „regex” pentru a sublinia izolarea lor de limbajele formale în general.

Învățați să scrieți regex

Expresiile regulate sunt descrise folosind două bare oblice ( // ) și potrivesc șiruri care se potrivesc cu modelul dintre ele. De exemplu, /Bună/ se potrivește cu „Bună”, astfel încât să putem verifica dacă un șir se potrivește cu acest model.

Caracterele din expresiile regulate sunt potrivite în ordinea în care sunt introduse. Asa de /Salut Lume/ răspunde la șirul „Bună lume”.

Puteți ușura căutarea cuvintelor arbitrare adăugând puțină magie regex: \w se potrivește cu orice „cuvânt” format numai din litere. Numerele sunt identificate folosind același principiu: \d .

Exemplul 1

Grozav, acum putem compara șiruri sau putem verifica dacă se potrivesc cu un anumit model. Ce urmeaza? Pot expresiile regulate să îndeplinească alte funcții?

Fiți siguri! Să presupunem că am scris un bot de chat IRC care reacționează dacă cineva scrie „Josh”. Botul nostru scanează fiecare mesaj până când găsește o potrivire. Apoi botul răspunde: „Woah, sper că nu vorbești de rău despre prietenul meu Josh!” („O, sper că nu vei vorbi de rău despre prietenul meu Josh!”). Pentru că numai roboții sunt prieteni cu Joshe.

Botul nostru folosește un șablon pentru a compara șirurile /Josh/ . La un moment dat, cineva pe nume Eli va spune: „Eli: Josh, chiar ai nevoie de atâta cofeină?” Botul nostru își va ciuli urechile, va detecta un potrivire și va da răspunsul său neașteptat, ceea ce îl va speria destul de pe Eli. Misiune completa! Sau nu?

Dacă botul nostru ar fi mai inteligent? Dacă el, de exemplu, s-ar adresa vorbitorului pe nume? Ceva de genul „Woah, sper că nu vorbești rău pe prietenul meu Josh, Eli”.

Cuantificatori (caractere care se repetă)

0 sau mai mult

Putem face asta... Dar mai întâi trebuie să înțelegem câteva lucruri. În primul rând - cuantificatori(pentru repetarea caracterelor). Poate fi folosit * pentru a indica 0 sau mai multe caractere după. De exemplu, /A*/ se poate potrivi atât cu „aaaaaaa” cât și cu „”. Da, ați auzit bine: va răspunde la un șir gol.

* servește la desemnarea a ceva opțional, întrucât simbolul căruia îi corespunde nu trebuie să existe deloc. Dar poate. Și de mai multe ori (teoretic, de nenumărate ori).
Puteți desemna „Josh” cu /Josh/ , dar putem specifica și modelul „Jjjjjjjjjosh” sau „osh”. /J*osh/ .

1 sau mai multe

Pentru a desemna unul sau mai multe caractere este folosit + . Funcționează eficient pe același principiu ca și * , cu excepția faptului că existența a cel puțin unui caracter nu mai este opțională: cel puțin unul trebuie să fie prezent.

Deci putem seta șablonul /J+osh/ șirurile „Josh” sau „Jjjjjjjjjosh”, dar nu „osh”.

Metacaracterele

Grozav, ne-am eliberat deja mâinile în multe feluri. Cineva s-ar putea să strige „Joooooosh” chiar acum dacă este deja suficient de supărat...

Dar dacă se enervează atât de mult încât chiar își lovește fața în tastatură de câteva ori? Cum desemnăm „aaavyopshadlorvpt” fără să știm dinainte cât de precis este nasul lui?
Prin utilizarea metacaracterele!

Metacaracterele vă permit să specificați absolut ORICE. Sintaxa lor este . . (Da, punct. Doar un punct.). Punem pariu că îl folosiți mult, așa că nu vă sfiați să îl folosiți pentru a marca sfârșitul unei propoziții.

Puteți seta „Joooafhuaisggsh” cu expresia /Jo+.*sh/ , combinând cunoștințele dobândite anterior despre caractere repetate și metacaractere. Pentru a fi precis, această expresie se potrivește cu un „J”, unul sau mai multe „o”, zero sau mai multe metacaractere și un „s” și un „h”. Aceste cinci blocuri ne conduc la ceea ce numim...

...grupuri de personaje

Grupuri de caractere- acestea sunt blocuri de caractere în care succesiunea componentelor este importantă. Ele sunt considerate ca un întreg. Folosind * sau + , de fapt specificați o secvență a unui grup de caractere care se repetă, nu doar ultimul caracter.

Acest lucru este util de înțeles ca tehnică de sine stătătoare, dar câștigă o funcționalitate mai mare atunci când este combinat cu simboluri repetate. Grupurile de caractere sunt specificate folosind paranteze (da, acei tipi).
Să presupunem că vrem să repetăm ​​„Jos”, dar nu „h”. ceva de genul „JosJosJosJosJosh”. Acest lucru se poate face cu expresia /(Jos)+h/ . Simplu, nu-i așa?

Dar în sfârșit... Revenind la primul nostru exemplu, cum obținem numele lui Eli în chat-ul nostru IRC din mesajul pe care l-a trimis?

Grupurile de caractere pot servi și pentru a reține subșiruri. Pentru a face acest lucru, ei fac de obicei ceva de genul \1 pentru a determina primul grup specificat.

De exemplu, /(.+) \1/ - un caz special. Aici vedem un set de caractere aleatorii repetate o dată sau de mai multe ori, un spațiu după el și apoi exact același set repetat din nou. Deci, o astfel de expresie se va potrivi cu „abc abc”, dar nu cu „abc def”, chiar dacă „def” în sine se potrivește (.*) .

Memorarea potrivirilor este foarte puternică și probabil se reduce la cea mai utilă caracteristică a expresiilor regulate.

Exemplul 2

Pf... În sfârșit, putem reveni la exemplul cu botul de chat IRC. Să ne punem în practică cunoștințele.

Dacă vrem să surprindem numele expeditorului mesajului când scrie „Josh”, expresia noastră ar arăta cam așa: /(\w+): .*Josh.*/ , și putem stoca rezultatul într-o variabilă în limbajul nostru de programare pentru răspuns.

Să ne uităm la expresia noastră regulată. Iată una sau mai multe litere care urmează „ : ”, 0 sau mai multe caractere, „Josh” și din nou 0 sau mai multe caractere.

Notă: /.*cuvânt.*/ este o modalitate simplă de a specifica un șir care conține „cuvânt”, care poate conține sau nu alte caractere.

În Python ar arăta astfel:
import re
model = re.compile(ur"(\w+): .*Josh.*") # Regex-ul nostru
șir = u"Eli: Josh du-te să-ți muți rufele" # Șirul nostru
potriviri = re.match(pattern, string) # Testează șirul
who = matchs.group(1) # Obțineți cine a spus mesajul
print(cine) # "Eli"
Observați că am folosit .Grupa 1) la fel ca \1 . Acest lucru nu este nimic nou, cu excepția utilizării expresiilor regulate în Python.

Început și sfârșit

Până în acest punct, am presupus că subșirurile pe care le căutăm pot fi localizate oriunde în șir. De exemplu, /(Jos)+h/ se potrivește cu orice șir care conține „Jos-repeated-h” în orice locație.

Dacă vrem ca șirul să înceapă cu acest model? Acesta poate fi notat ca /^(Jos)+h/ , Unde ^ se potrivește cu începutul liniei. De asemenea, $ marchează sfârșitul liniei.

Acum, dacă vrem să specificăm un șir care conține doar „Jos-repeating-h”, vom scrie /^(Jos)+h$/ .

Enumerarea expresiilor

Imaginați-vă că scrieți o expresie obișnuită pentru o rețetă de sandvișuri. Nu știi dacă clientul preferă pâinea albă sau neagră, dar tot trebuie să alegi doar una. Cum se adaugă selecție la regex? Prin utilizarea transferuri!

Acestea vă permit să specificați seturi de valori posibile pentru un grup de caractere. Arata cam asa: (alb|grâu) . În contextul exemplului nostru de sandviș, una dintre opțiuni va fi acceptată - fie „alb”, fie „grâu”.

Pentru a desemna enumerări, [parantezele pătrate] sunt folosite oarecum diferit. În loc de întreg șirul, fiecare caracter este o variantă aici. Acest lucru poate fi util pentru expresiile regulate complexe, deoarece puteți înlocui un singur caracter cu un set mai complex.

Modificatori

Vorbeam despre regex cu /două bare oblice/, nu? Știm ce este între ei, dar ce ar trebui să fie afară?

Întorsătură neașteptată: nimic!

…stânga. Partea dreaptă, pe de altă parte, poate conține multe, multe lucruri utile. Este păcat că nu am spus un cuvânt despre asta atât de mult timp!
Modificatori definiți regulile prin care se aplică expresiile regulate.

Iată o listă a modificatorilor principali (de la Regex101.com):

Modificator Nume Descriere
g global Toate meciurile
m multi-linie ^ și $ se potrivesc cu începutul și sfârșitul fiecărei linii
i insensibil Comparație fără majuscule
X extins Spațiile și textul după # sunt ignorate
X suplimentar \ cu o literă arbitrară care nu are o semnificație specială returnează o eroare
s o singura linie Ignoră liniile noi
u unicode Șirurile de șabloane sunt procesate ca UTF-16
U nelacom În mod implicit, regex utilizează cuantificare leneșă. Modificatorul U face cuantificarea lacomă
A ancorat Modelul este forțat să ^
J duplicat Permite nume de submodel duplicat

Pentru claritate, toate exemplele anterioare au fost sensibile la majuscule și minuscule. Aceasta înseamnă că dacă înlocuiți chiar și o literă mică cu una mare sau invers, șirul nu se va mai potrivi cu modelul. Dar îl puteți face indiferent de majuscule și minuscule folosind un modificator i .

Să presupunem că Eli s-a supărat atât de mult încât a început să bombardeze chat-ul cu mesaje cu SCRISORI DE DIFERITE REGISTRE. Acest lucru nu ne sperie, pentru că sunt deja aici! Putem defini cu ușurință expresia furioasă „Urăsc să trăiesc cu JOSH!!!” cu modelul /i ha+te living with josh!+/i . Regex-ul nostru este acum mai ușor de citit și, de asemenea, mult mai puternic și util. Uimitor!

Puteți juca singur cu diferiți modificatori. În opinia mea, în general vei beneficia cel mai mult igm .

Ce urmeaza?

Sper că acest articol mi-a permis să privesc diferit lucrul cu șiruri și să-l fac mai rezonabil. Am zgâriat doar suprafața, dar ați învățat deja cum să utilizați regex pentru a rezolva unele probleme.

Există multe caractere și combinațiile lor folosite în expresiile regulate. De obicei, le veți întâlni în timp ce explorați Stack Overflow, dar puteți ghici semnificația unora din exemplele anterioare (de exemplu, \n - simbol de linie nouă). S-a pus bazele, dar mai sunt multe de învățat.

Puteți găsi o listă completă de combinații de simboluri și, de asemenea, vă puteți testa cunoștințele.
Dacă ți s-a părut o bucată de tort, încearcă cuvintele încrucișate regex. Chiar te vor face să transpiri.

După punct

Acest articol este o traducere a ghidului lui Josh Hawkins. Josh este un dezvoltator web pasionat din Alabama. A început să programeze la vârsta de nouă ani, concentrându-se pe jocuri video, desktop și unele aplicații mobile. Cu toate acestea, în timpul unui stagiu în 2015, Josh a descoperit dezvoltarea web și a pătruns în lumea open source legată de acest domeniu.

Iată câteva exemple de expresii regulate.

    karova - evident un șablon în care se încadrează cuvântul karova;

    \b(shift|unshift|pop|push|splice)\b - oricare dintre cuvintele enumerate;

    ^\s+ - unul sau mai multe spații sau file la începutul unei linii.

În expresiile regulate, caracterele alfanumerice se reprezintă de obicei. De exemplu, modelul Hello specifică căutarea caracterului H urmat de e , apoi l , etc.

Dacă un simbol este dificil sau incomod de specificat literal, puteți folosi literale deja cunoscute de noi: \n , \t și altele. Aceasta înseamnă că caracterul \ inclus în expresia regulată nu se mai poate autodesemna, deoarece schimbă semnificația caracterului care îl urmează: în special, litera n, împreună cu caracterul backslash precedent, denotă caracterul de sfârșit de linie. Dacă doriți să includeți caracterul \ însuși în model, ar trebui să utilizați literalul \\ .

Există și alte simboluri cărora li se dă o semnificație specială în tipare, în loc să se reprezinte. Astfel de simboluri sunt numite metacaracterele. Să dăm câteva exemple de metacaractere, fără a indica încă semnificația lor specială (lista nu este exhaustivă): \.-()()?*+^$| .

Unele personaje nu se dovedesc întotdeauna a fi metacaractere, ci doar atunci când se încadrează într-un anumit context. Unele metacaractere au semnificații diferite în funcție de context.

Dacă trebuie să inserați un metacaracter într-o expresie obișnuită, făcându-l să nu mai aibă sens, ar trebui să îl protejați ( scut), plasând o bară oblică inversă în fața lui. De exemplu, un semn plus într-o expresie regulată este inserat ca \+ .

Modelul desemnează unul dintre caracterele enumerate între paranteze drepte. Dacă, de exemplu, ne interesează cuvântul Bună ziua, nu contează dacă este scris cu majuscule sau mic, modelul va fi astfel: ello. Iată un model care reprezintă o literă vocală mică în alfabetul englez: . Un alt exemplu este o clasă de caractere formată din ambele paranteze drepte: [\[\]] .

Dacă o clasă de caractere include caractere care sunt consecutive în tabelul de coduri, este suficient să indicați primul și ultimul caracter, inserând o cratimă între ele. De exemplu, o clasă care reprezintă orice cifră zecimală poate fi specificată ca . O literă din alfabetul englez este desemnată ca (aici ne bazăm pe faptul că, în orice tabel de coduri, literele engleze mari și mici apar în blocuri învecinate în ordine alfabetică; totuși, un bloc de litere mici nu urmează imediat un bloc de litere mari litere).

Este posibil să se definească o clasă de caractere formată din toate caracterele, cu excepția celor enumerate - așa-numitele negarea clasei de caractere. Pentru a face acest lucru, un semn circumflex ^ este inserat imediat după paranteza pătrată de deschidere înainte de enumerare. Orice caracter care nu este un număr poate fi reprezentat ca [^0-9] .

Există notații speciale pentru unele clase de caractere populare:

Când un șir este potrivit cu o expresie regulată, fiecare caracter sau clasă de caractere din șablon este potrivit cu un caracter din șir. Există însă construcții care nu indică prezența unui anumit personaj, ci un anumit loc (gol) în linie. Astfel de construcții se numesc legături, sau ancore

Cele mai frecvent utilizate ancore sunt ancora (^) și capătul ($) al șirului. Ancora de început de linie trebuie plasată la începutul modelului, iar ancora de capăt de linie ar trebui să fie plasată la sfârșit.

De exemplu, cuvintele rusești precum antidot, antisemitism sau antiparticulă se potrivesc tiparului ^anti. Fără o legătură, liniile care nu încep cu „anti-”, dar care conțin această combinație de litere în interior, ar fi de asemenea potrivite, de exemplu, mercantilism. Pentru a căuta cuvinte care se termină în „-tsya” aveți nevoie de modelul tsya$ (sîntem aproape 100% siguri că toate astfel de cuvinte sunt verbe reflexive la infinitiv). Nimic nu vă împiedică să utilizați ambele legături în șablon.

O altă ancoră utilă este cuvântul boundary anchor \b . Se potrivește spațiul dintr-un șir dintre caractere, dintre care unul este de clasa \w și celălalt de clasa \W (în orice ordine). Această ancoră poate potrivi și începutul sau sfârșitul unui șir (caz în care șirul este considerat a fi înconjurat de caractere imaginare din clasa \W).

Dacă căutăm un fragment care să se potrivească cu unul dintre mai multe șabloane, trebuie să enumerăm aceste șabloane, separate printr-o țeavă | . De exemplu, luni|marți|miercuri|joi|vineri|sâmbătă|duminică. Pentru ca lista de alternative să fie o unitate independentă și separată de cele învecinate, aceasta trebuie inclusă între paranteze. De exemplu, modelul Respected înseamnă șirul Respected urmat de unul dintre șirurile th sau th. Fără paranteze, modelul Dear|aya ar indica unul dintre șirurile Dear sau aya. Parantezele au un efect secundar important, care va fi discutat în secțiunea „Gruparea și capturarea”.

Pentru a indica de câte ori se poate repeta un model, așa-numitul cuantificatori(din cuvântul latin cuantic- Câți):

Cuantificatori * , + și ? sunt redundante deoarece pot fi exprimate diferit folosind bretele. Și anume, * este echivalent cu (0,) , + este echivalent cu (1,) , nu? - la fel ca (0,1) . Dar acești cuantificatori sunt foarte des folosiți și, prin urmare, merită denumiri separate.

Dacă modelul căruia i se aplică cuantificatorul este ceva mai complex decât un singur caracter sau o singură clasă de caractere, acesta trebuie să fie cuprins între paranteze.

Aici sunt cateva exemple:

    ^\d+$ - o secvență de una sau mai multe cifre zecimale (un model pentru numere întregi nenegative în notație zecimală);

    ^\-?\d+$ - același lucru, dar pentru toate numerele întregi (eventual negative);

    ^\-?(\d+(\.\d*)?|\.\d+)$ - model pentru numere reale;

Să ne uităm la ultimul exemplu mai detaliat. Pe lângă semnul minus opțional de la început, modelul conține un grup cu două alternative: \d+(\.\d*)? și \.\d+ . Prima alternativă include o parte întreagă necesară \d+ (cel puțin o cifră), urmată de o parte fracțională opțională (\.\d*)? . Partea fracțională, dacă există una, are un punct zecimal și, eventual, mai multe cifre. Astfel, această alternativă corespunde liniilor 15, 15., 15.487. O altă alternativă este necesară pentru șirurile de forma .618 cu o parte întreagă lipsă - în multe limbaje de computer, această intrare are dreptul de a exista.

Dacă cele mai simple elemente ale unei expresii regulate - caractere, clase de caractere și ancore - sunt scrise într-un rând, aceasta înseamnă că atunci când un model este căutat într-un șir, aceste elemente vor fi potrivite cu părți ale șirului secvențial, în aceeași secvență . Acest ordin este încălcat dacă se aplică alternative. Vă puteți imagina că o expresie regulată compusă este formată din expresii simple folosind două operații: îmbinare secvențială ( compozitii) și alternative. Compoziția este un analog al operației de înmulțire din aritmetică. O alternativă este un analog al adăugării. Prima asemănare cu aritmetica este că operația alternativă are o prioritate mai mică decât compoziția, așa că poate fi necesară gruparea parantezelor, ca în exemplul Dear.

Notă

Multe, deși nu toate, legi ale aritmeticii se aplică și expresiilor regulate:

comutativitatea alternativei x | y = y | X ; asociativitatea alternativei x | y | z = x | y | z; asociativitatea compoziției x ⁣ y ⁣ z = x ⁣ y ⁣ z ; distributivitatea alternativei în raport cu compoziția (stânga și dreapta) x și | z = x ⁣ y | x ⁣ z , x | y z = x z | yz .

În această ciudată aritmetică a expresiilor regulate, legea comutativității pentru compoziție nu este valabilă. În plus, nu există un analog de zero datorită relației evidente x | x = x . Rolul de unitate (dreapta și stânga) pentru compoziție este jucat de un șablon gol (să-l notăm 𝟙): 𝟙 ⁣ x = x ⁣ 𝟙 = x. Cuantificatorii de forma ( n ) joaca rolul de a ridica la a n-a putere.

Pe lângă funcția de grupare, parantezele îndeplinesc o funcție de captare. Principalul rezultat al potrivirii unui șir cu un model este răspunsul la întrebarea: șirul se potrivește cu modelul? Dar, în plus, este adesea necesar să se determine ce fragment sau fragmente dintr-un șir se potrivesc cu anumite fragmente într-o expresie regulată.

Sau poate acid etilendiamină-N N N ′ N ′-tetraacetic?

Să luăm în considerare un exemplu în care în text se găsesc referiri la diferiți acizi. Amintirile noastre de școală din chimie ne-au condus la ideea că numele acizilor se termină fie în vaya, fie naya, fie taya și apoi, după un spațiu, urmează cuvântul acid. Facem un șablon: \S+[int]acid. Potrivim textul cu șablonul. Noroc! Dar, cineva se întreabă, ce fel de acid a fost menționat în text? Sărat? Sulf? Azot? Plavikova? Clor? Cloric? Ipocloros? Lămâie? Cianil? Dezoxiribonucleic?

Aici mânerul este la îndemână. Anexăm acea parte a șablonului care, conform planului nostru, ar trebui să corespundă numelui dintre paranteze: (\S+[int]th) acid. Apoi mașina, după ce a găsit o mențiune a acidului în text, își va salva numele (ceea ce corespunde fragmentului de șablon cuprins între paranteze) într-o variabilă specială - tampon de captare

O expresie regulată poate conține mai multe grupuri de captură. Astfel de grupuri nu numai că se pot urma unul pe celălalt, ci și se pot cuibăre unul în celălalt. Cu alte cuvinte, expresia regulată trebuie echilibrată cu parantezele, în același sens ca cel discutat în capitolul 23." Verificarea echilibrului parantezelor" (desigur, acest lucru se aplică doar parantezelor care servesc scopului grupării și captării; parantezele precedate de o bară oblică inversă nu au niciun efect asupra echilibrului grupului). Dacă căutarea are succes, fiecare grup va captura o parte din text: prima - în primul buffer, a doua - în al doilea și așa mai departe. Cum sunt numerotate grupurile atunci când sunt imbricate unul în celălalt? Numerotarea este în ordinea în care apar parantezele de deschidere:

2 4 5 ┝┑ ┝┑┝┑ (()(()())) │ ┝━━━━┙│ │ 3 │ ┝━━━━━━━━┙ 1

Dacă se dorește, un grup poate fi exclus din numerotare, adică lipsit de funcția sa „agresivă”, lăsând doar funcția de grupare. Pentru a face acest lucru, în loc de delimitatori de grup (⋯), folosim ( ?: ⋯) . Există un semn de întrebare aici Nu denotă un cuantificator deoarece cuantificatorul trebuie să fie precedat fie de un caracter, de o clasă de caractere, fie de un grup.

Utilizarea grupurilor de captură numerotate nu este întotdeauna convenabilă, mai ales în expresiile regulate mari. De îndată ce inserați un nou grup de captură în șablon, numerotarea se pierde. Apoi va trebui să faceți corecții în toate locurile din program unde se accesează bufferele de captură după număr. Cu toate acestea, puteți asocia un nume cu un grup care vă permite să accesați tamponul corespunzător cu acel nume. Pentru a crea un grup numit, utilizați delimitatori ( ? ⋯) , unde numele dorit este înlocuit cu numele.

Părțile unui șir capturate în buffer-uri pot fi utilizate în două moduri. În primul rând, un program care utilizează o expresie regulată pentru a găsi sau înlocui se poate referi la buffer-uri ca variabile speciale. Această utilizare va fi discutată în secțiunea „Căutare și înlocuire operatori”. A doua posibilitate presupune utilizarea link-urilor către grupuri direct într-o expresie obișnuită, vezi secțiunea „Backlink-uri”.

Luați în considerare problema găsirii cuvintelor care conțin trei litere vocale identice la rând. Soluția naivă [aеооуеуя](3) folosind cuantificatori nu va funcționa, deoarece acest model se potrivește șiruri cu trei vocale consecutive, dar nu neapărat aceleași. Respingem cu indignare o soluție monstruoasă cu o enumerare completă de alternative, aaa|eeee|yoyo|iii|oooo|uuu|eeee|yuyuyu|yayay: la urma urmei, merită să luăm o altă clasă simbolică, mai extinsă, sau să înlocuim triplul în cuantificator cu o valoare mai mare, cum ar fi dimensiunea șablonului, va crește catastrofal.

Cu toate acestea, o soluție elegantă este posibilă folosind grupuri de captură. Să captăm vocala într-un grup și apoi să facem referire la conținutul tamponului de capturare. Referințele la primul, al doilea, al treilea buffer sunt scrise într-o expresie regulată ca \g1, \g2, \g3. Deci, soluția este modelul ([aeeioueyuya])\g1(2) . Vă rugăm să rețineți că referința la tamponul de captare trebuie să vină strict după grupul corespunzător din expresia regulată.

Backlink-urile se pot referi nu numai la bufferele numerotate, ci și la cele numite. Astfel de legături arată ca \k , unde, din nou, în loc de nume există un nume specific. Exemplul nostru poate fi rescris folosind grupuri numite: (? [aeeyoooeyya])\k {2} (vocală- vocală).

Uneori este nevoie de o căutare care să nu facă distincția între literele mici și mari. Această căutare se numește insensibil la majuscule (insensibil la majuscule). În loc să înlocuim literele peste tot în șablon cu clase de două litere (a → , b → , ...), pur și simplu să includem șablonul într-un grup special care include modul de căutare fără majuscule: (? eu:⋯) . Un astfel de grup nu este un grup de captură. Dacă căutarea care nu ține seama de majuscule și minuscule trebuie implementată doar pe o parte a expresiei regulate, atunci numai partea necesară ar trebui plasată în grup.

Dimpotrivă, dacă o parte a expresiei regulate în care se efectuează căutarea fără diferențiere între majuscule și minuscule trebuie să dezactiveze acest mod, atunci puteți reveni la căutarea obișnuită, care diferențiază majuscule și minuscule folosind grupul ( ?-i: ⋯) .

Modurile sensibile la majuscule/minuscule afectează numai literele. Ceea ce contează ca o literă și ce nu depinde de limbă, la fel și regulile de potrivire a literelor mari și mici. Din punctul de vedere al limbii engleze, de exemplu, simbolul Ш nu este o literă.În limba germană există litera ß (apropo, versiunea majusculă a acestei litere este formată din două litere SS: Carl Friedrich Gauß → CARL FRIEDRICH GAUSS).

Expresiile regulate sunt o modalitate utilizată pe scară largă de a descrie modele pentru căutarea textului și verificarea dacă textul se potrivește cu un model. Metacaracterele speciale vă permit să specificați, de exemplu, că căutați un subșir la începutul șirului de intrare sau un anumit număr de repetări ale subșirului.

La prima vedere, expresiile regulate par înfricoșătoare (bine, la a doua vedere par și mai înfricoșătoare ;)).

Vă recomand cu tărie să vă „jucați” cu programul demo pentru Windows REStudio furnizat în kitul de distribuție - acest lucru vă va permite să înțelegeți mai bine principiul expresiilor regulate și să vă depanați propriile expresii. TestRExp include, de asemenea, multe exemple de expresii.

Mai jos este o descriere a unui subset de sintaxă a expresiilor regulate care funcționează în aproape toate implementările și este susținută de biblioteca mea Delphi, care este inclusă ca standard în Lazarus (Free Pascal).

Să începem introducerea în expresiile regulate!

Comparație simplă

Orice caracter se potrivește cu el însuși, cu excepția cazului în care aparține metacaracterelor speciale descrise mai jos.

Secvența de caractere se potrivește cu aceeași secvență din șirul de intrare, astfel încât modelul bluh se va potrivi cu subșirul bluh din șirul de intrare. Până acum totul este simplu, nu-i așa?

Dacă metacaracterele sau secvențele de evadare trebuie tratate ca caractere obișnuite, acestea trebuie să fie precedate de un caracter \, de exemplu, metacaracterul ^ se potrivește de obicei cu începutul rândurilor, totuși, dacă este scris ca \^ se va potrivi cu caracterul ^, \ \ se potrivește cu \ etc.

Exemple:

foobar găsește „foobar” \^FooBarPtr găsește „^FooBarPtr”

Secvențe de evadare

Orice caracter poate fi specificat folosind o secvență de escape, așa cum se face în C sau Perl: \n înseamnă începutul unei linii, \t înseamnă o tabulație etc. În general, \xnn , unde nn este o secvență hexazecimală cifre, înseamnă caracter cu cod ASCII nn. Dacă trebuie să specificați un caracter pe doi octeți (Unicode), utilizați formatul \x(nnnn) , unde nnnn este una sau mai multe cifre hexazecimale.

\xnn caracter cu cod hexazecimal nn \x(nnnn) caracter cu cod hexazecimal nnnn (mai mult de un octet pot fi specificati numai în modul (tregexpr_interface.html#unicode))| \t tab (HT/TAB), puteți, de asemenea, \x09 \n linie nouă (NL), puteți, de asemenea, \x0a \r retur car (CR), puteți, de asemenea, \x0d| Traducere în format \f (FF), puteți și \x0c| \a apel (BEL), puteți, de asemenea, \x07| \e escape (ESC), de asemenea \x1b|

Exemple:

foo\x20bar găsește „foo bar” (notați spațiul din mijloc) \tfoobar găsește „foobar” precedat de o filă

Liste de simboluri

Puteți defini o listă prin includerea caracterelor în . Lista se va potrivi cu orice caracter listat în ea.

Dacă primul caracter al listei (imediat după [) este ^, atunci o astfel de listă se potrivește cu orice caracter care nu este listat în listă.

Exemple:

foobr găsește „foobar”, „foober”, etc. dar nu „foobbr”, „foobcr” etc. foob[^aeiou]r găsește „foobbr”, „foobcr”, etc.. dar nu „foobar”, „foober”, etc.

În cadrul unei liste, caracterul - poate fi folosit pentru a defini intervale de caractere, de exemplu a-z reprezintă toate caracterele între a și z, inclusiv.

Dacă trebuie să includeți caracterul însuși în listă, plasați-l la începutul sau la sfârșitul listei sau precedați-l cu \. Dacă trebuie să includeți caracterul ] în listă, plasați-l chiar la început sau precedați-l cu \.

Exemple:

[-az] „a”, „z” și „-” „a”, „z” și „-” „a”, „z” și „-” toate cele 26 de litere mici latine de la „a” la „z” [\n-\x0D] #10, #11, #12, #13. [\d-t] cifră, „-” sau „t”. -a] caracter din intervalul „]”..”a”.

Metacaracterele

Metacaracterele sunt caractere speciale care sunt cel mai important concept în expresiile regulate. Există mai multe grupuri de metacaractere.

Metacaracterele - separatoare de linii

^ începutul rândului $ sfârşitul rândului \A început de text \Z sfârşitul textului. orice caracter din șir

Exemple:

^foobar găsește „foobar” numai dacă este la începutul liniei foobar$ găsește „foobar” numai dacă este la sfârșitul liniei ^foobar$ găsește „foobar” doar dacă este singurul cuvânt din linia foob .r găsește „foobar”, „foobbr”, „foob1r” etc.

Metacaracterul ^ se potrivește implicit numai la începutul textului introdus, iar metacaracterul $ se potrivește doar la sfârșitul textului. Separatoarele de linii interne prezente în text nu se vor potrivi cu ^ și $ .

Cu toate acestea, dacă trebuie să tratați textul ca pe mai multe linii, astfel încât ^ să se potrivească după fiecare separator de linie din text și $ să se potrivească înainte de fiecare delimitator, atunci puteți include modificatorul /m.

Metacaracterele \A și \Z sunt similare cu ^ și $, dar nu sunt afectate de modificatorul /m, adică. se potrivesc întotdeauna doar la începutul și la sfârșitul întregului text introdus.

Metacaracter. implicit se potrivește cu orice caracter, totuși, dacă dezactivați modificatorul /s, atunci. nu se potrivesc cu separatorii de linii.

TRegExpr interpretează separatorii de linii așa cum se recomandă pe www.unicode.org:

^ se potrivește cu începutul textului introdus și, de asemenea, dacă este inclus modificatorul /m, punctul imediat după \x0D\x0A , \x0A sau \x0D (dacă utilizați versiunea Unicode

$ se potrivește cu sfârșitul textului introdus și, de asemenea, dacă este inclus modificatorul /m, punctul care precede imediat \x0D\x0A , \x0A sau \x0D (dacă utilizați versiunea Unicode a TRegExpr, atunci și \x2028 sau \ x2029 sau \x0B sau \x0C sau \x85). Rețineți că nu se potrivește în secvența \x0D\x0A .

Se potrivește cu orice caracter, dar dacă modificatorul r /s este dezactivat, atunci. nu se potrivește cu \x0D\x0A și \x0A și \x0D (dacă utilizați versiunea Unicode a TRegExpr, nu se potrivește cu \x2028 și \x2029 și \x0B și \x0C și \x85).

Rețineți că ^.*$ (modelul pentru șirul gol) nu se potrivește cu șirul gol, cum ar fi \x0D\x0A , dar se potrivește cu \x0A\x0D .

Puteți reconfigura comportamentul de mai sus atunci când procesați texte cu mai multe linii - vedeți descrierile proprietăților LineSeparators și LinePairedSeparator, de exemplu, puteți reconfigura pentru a utiliza numai separatoare de linie Unix \n sau numai separatoare DOS/Windows \r\n sau separatoare mixte (sau configurat implicit) sau chiar definiți-vă propriile separatoare de linii!

Metacaractere - liste standard de personaje

\w caracter alfanumeric sau „_” \W nu \w \d caracter numeric \D nu \d \s orice caracter „spațiu alb” (implicit este [ \t\n\r\f]) \S nu \ s

Listele standard \w , \d și \s pot fi utilizate și în interiorul listelor de caractere.

Exemple:

foob\dr găsește „foob1r”, „”foob6r”, etc. dar nu „foobar”, „foobbr”, etc. foob[\w\s]r găsește „foobar”, „foob r”, „foobbr” etc. dar nu „foob1r”, „foob=r” etc.

Metacaracterele - opțiuni

Puteți defini o listă de opțiuni folosind metacaracterul | pentru a le separa, de exemplu fee|fie|foe se va potrivi cu fee sau fie sau foe , (la fel ca f(e|i|o)e). Ca prima opțiune, totul de la metacaracterul anterior (sau [ sau de la începutul expresiei la primul metacaracter | este perceput, ca ultimă opțiune - totul de la ultimul | până la sfârșitul expresiei sau la cel mai apropiat metacaracter) . De obicei, pentru a evita confuzia, setul de opțiuni este întotdeauna cuprins între paranteze, chiar dacă acest lucru ar putea fi făcut fără.

Opțiunile sunt încercate începând de la prima și încercările sunt finalizate de îndată ce este posibil să se selecteze una în care se potrivește întreaga parte ulterioară a expresiei (pentru mai multe detalii, vezi mecanismul de funcționare). Aceasta înseamnă că variantele nu vor furniza neapărat un comportament lacom. De exemplu, dacă aplicați expresia foot|foot la șirul de intrare barefoot , acesta va găsi foo deoarece este prima opțiune care permite ca întreaga expresie să se potrivească.

Rețineți că metacaracterul | este perceput ca un caracter obișnuit în interiorul listelor de caractere, de exemplu, înseamnă exact la fel ca .

Exemple:

foo(bar|foo) se potrivește cu „foobar” sau „foofoo”.

Metacaracterele - subexpresii

Metacaracterele (...) pot fi folosite și pentru a specifica subexpresii

  • După finalizarea căutării unei expresii, puteți accesa orice subexpresie folosind proprietățile MatchPos, MatchLen și Match și, de asemenea, puteți înlocui subexpresii într-un șablon folosind metoda Substitute).

Subexpresiile sunt numerotate de la stânga la dreapta, în ordinea în care apar parantezele de deschidere.

Prima subexpresie are numărul 1 (întreaga expresie este 0", poate fi accesată în Substitute fie $0" fie $&).

Exemple:

(foobar)(8,10) găsește un șir care conține 8, 9 sau 10 copii ale „foobar” foob(|a+)r găsește „foob0r”, „foob1r”, „foobar”, „foobaar”, „foobaar”, etc. . .

Metacaracterele - backlink-uri

Metacaracterele de la \1 la \9 sunt tratate ca backlink. \ se potrivește cu subexpresia găsită anterior # .

Exemple:

(.)\1+ găsește „aaaa” și „cc”. (.+)\1+ se potrivește, de asemenea, cu „abab” și „123123” ([””]?)(\d+)\1 se potrivește cu „13” (între ghilimele duble) sau „4” (între ghilimele simple) sau 77 (fără ghilimele), etc.

Modificatori

Modificatorii sunt utilizați pentru a schimba modurile de funcționare ale TRegExpr.

Puteți schimba modificatorii în mai multe moduri.

Orice modificator poate fi modificat folosind o construcție specială (?...) în interiorul unei expresii regulate.

De asemenea, puteți atribui o valoare proprietății corespunzătoare a instanței obiectului TRegExpr (de exemplu, ModifierX pentru a modifica modificatorul /x sau ModifierStr pentru a modifica mai mulți modificatori simultan). Valorile implicite pentru noile instanțe ale obiectelor TRegExpr sunt definite în , de exemplu RegExprModifierX definește valoarea implicită pentru ModifierX.

i

Modul care nu ține seama de majuscule și minuscule (în mod implicit folosește limba implicită selectată în sistemul de operare), (vezi și InvertCase)

m

s

g

Nu este un modificator standard. Opriți-l, comutați toate repetoarele în modul „non-lacom” (acest modificator este activat implicit). Acestea. Dacă îl dezactivați, atunci toate + funcționează ca +? , * Cum *? etc.

X

Vă permite să formatați șablonul pentru a fi mai ușor de citit (vezi descrierea de mai jos).

r

Nu este un modificator standard. Dacă este activat, intervalele precum a-z includ și litera ё, A-Z includ Ё și a-Z include toate literele rusești în general.

Modificatorul /x face ca TRegExpr să ignore spațiile, tabulatorii și separatorii de linii, permițând formatarea textului expresiei. În plus, dacă este întâlnit caracterul #, atunci toate caracterele ulterioare până la sfârșitul rândului sunt tratate ca un comentariu, de exemplu:

((abc) # Comentariu 1 | # Spațiile din expresie sunt de asemenea ignorate (efg) # Comentariu 2)

Desigur, aceasta înseamnă că, dacă trebuie să inserați un spațiu, tabulație sau separator de linii sau # într-o expresie, atunci în modul extins (/x) acest lucru se poate face doar precedându-le cu / sau folosind /xnn (în listele de caractere , toate aceste personaje sunt tratate ca de obicei)

Extensii Perl

(?imsxr-imsxr)

Vă permite să modificați valorile modificatorului

Exemple:

(?i)Sankt-Petersburg găsește „Sankt-Petersburg” și „Sankt-Petersburg” (?i)Saint-(?-i)Petersburg găsește „Sankt-Petersburg” dar nu „Sankt-Petersburg” (?i)(Sfântul -)?Petersburg găsește „Sankt-Petersburg” și „sfântul-petersburg” ((?i)Saint-)?Petersburg găsește „sfântul-Petersburg”, dar nu „sfântul-petersburg”