Noțiuni de bază privind expresia regulată în C ++

Regular Expression Basics C



Luați în considerare următoarea propoziție între ghilimele:

- Iată omul meu.

Acest șir poate fi în interiorul computerului, iar utilizatorul poate dori să știe dacă are cuvântul om. Dacă are cuvântul bărbat, el poate dori să schimbe cuvântul bărbat în femeie; astfel încât șirul să citească:







- Iată femeia mea.

Există multe alte dorințe ca acestea de la utilizatorul computerului; unele sunt complexe. Expresia regulată, prescurtată, regex, face obiectul gestionării acestor probleme de către computer. C ++ vine cu o bibliotecă numită regex. Deci, un program C ++ pentru a gestiona regex ar trebui să înceapă cu:



#include

#include

folosind spațiul de nume std;

Acest articol explică noțiunile de bază privind expresia regulată în C ++.



Conținutul articolului

Noțiuni fundamentale privind expresia

Regex

Un șir ca Iată omul meu. mai sus este secvența țintă sau șirul țintă sau pur și simplu ținta. omul, care a fost căutat, este expresia regulată sau, pur și simplu, regex.





Potrivire

Potrivirea se spune că apare atunci când este localizat cuvântul sau expresia căutată. După potrivire, poate avea loc o înlocuire. De exemplu, după ce bărbatul este situat deasupra, acesta poate fi înlocuit cu femeie.

Potrivire simplă

Următorul program arată cum se potrivește cuvântul om.



#include

#include

folosind spațiul de nume std;

intprincipal()
{

regex reg('om');
dacă (regex_search(- Iată omul meu.,reg))
cost<< „asortat” <<endl;
altceva
cost<< „nu se potrivește” <<endl;

întoarcere 0;
}

Funcția regex_search () returnează true dacă există o potrivire și returnează false dacă nu apare nicio potrivire. Aici, funcția ia două argumente: primul este șirul țintă, iar al doilea este obiectul regex. Regexul în sine este „om”, între ghilimele duble. Prima afirmație din funcția main () formează obiectul regex. Regex este un tip, iar reg este obiectul regex. Ieșirea programului de mai sus este „potrivită”, deoarece „om” este văzut în șirul țintă. Dacă „om” nu ar fi fost văzut în țintă, regex_search () ar fi returnat fals, iar rezultatul ar fi fost „nepotrivit”.

Ieșirea următorului cod nu se potrivește:

regex reg('om');
dacă (regex_search(- Iată ce fac.,reg))
cost<< „asortat” <<endl;
altceva
cost<< „nu se potrivește” <<endl;

Nu se potrivește deoarece „omul” regex nu a putut fi găsit în întregul șir țintă, „Iată ce fac eu”.

Model

Expresia regulată, omul de mai sus, este foarte simplă. Regexele nu sunt de obicei atât de simple. Expresiile regulate au metacaractere. Metacaracterele sunt personaje cu semnificații speciale. Un metacaracter este un personaj despre personaje. Metacaractere regex C ++ sunt:

^$ .* + ? ( ) [ ] { } |

O regex, cu sau fără metacaractere, este un model.

Clasele de caractere

Paranteza patrata

Un model poate avea caractere între paranteze drepte. Cu aceasta, o anumită poziție din șirul țintă se potrivește cu oricare dintre caracterele parantezelor pătrate. Luați în considerare următoarele obiective:

- Pisica este în cameră.

- Liliacul este în cameră.

- Șobolanul este în cameră.

Regexul, [cbr] at s-ar potrivi cu pisica din prima țintă. S-ar potrivi cu liliacul în a doua țintă. S-ar potrivi cu șobolanul în a treia țintă. Acest lucru se datorează faptului că, pisica sau liliacul sau șobolanul începe cu „c” sau „b” sau „r”. Următorul segment de cod ilustrează acest lucru:

regex reg(„[cbr] at”);
dacă (regex_search(- Pisica este în cameră.,reg))
cost<< „asortat” <<endl;
dacă (regex_search(- Liliacul este în cameră.,reg))
cost<< „asortat” <<endl;
dacă (regex_search(- Șobolanul este în cameră.,reg))
cost<< „asortat” <<endl;

Ieșirea este:

asortat

asortat

asortat

Gama de caractere

Clasa, [cbr] din modelul [cbr], ar corespunde mai multor caractere posibile din țintă. S-ar potrivi cu „c” sau „b” sau cu „r” în țintă. Dacă ținta nu are „c” sau „b” sau „r”, urmată de la, nu ar exista nicio potrivire.

Unele posibilități precum „c” sau „b” sau „r” există într-un interval. Gama de cifre, de la 0 la 9 are 10 posibilități, iar modelul pentru aceasta este [0-9]. Gama de alfabete minuscule, de la a la z, are 26 de posibilități, iar modelul pentru aceasta este [a-z]. Gama de alfabete majuscule, de la A la Z, are 26 de posibilități, iar modelul pentru aceasta este [A-Z]. - nu este oficial un metacaracter, dar între paranteze pătrate ar indica un interval. Deci, următoarele produc o potrivire:

dacă (regex_search(„ID6id”,regex(„[0-9]”)))

cost<< „asortat” <<endl;

Rețineți cum a fost construit regexul ca al doilea argument. Meciul are loc între cifra, 6 în interval, 0 la 9 și 6 în țintă, ID6id. Codul de mai sus este echivalent cu:

dacă (regex_search(„ID6id”,regex(„[0123456789]”)))

cost<< „asortat” <<endl;

Următorul cod produce o potrivire:

charstr[] = „ID6iE”;

dacă (regex_search(str,regex(„[a-z]”)))

cost<< „asortat” <<endl;

Rețineți că primul argument aici este o variabilă șir și nu literalul șir. Meciul este între „i” în [a-z] și „i” în ID6iE.

Nu uitați că o gamă este o clasă. Poate fi text în dreapta intervalului sau în stânga intervalului în model. Următorul cod produce o potrivire:

dacă (regex_search(„ID2id este un ID ',regex(„ID [0-9] id”)))

cost<< „asortat” <<endl;

Meciul este între ID [0-9] id și ID2id. Restul șirului țintă, este un ID, nu se potrivește în această situație.

Așa cum este utilizat în subiectul expresiei regulate (regexuri), cuvântul clasă înseamnă de fapt un set. Adică, unul dintre personajele din set trebuie să se potrivească.

Notă: Cratima - este un metacaracter numai între paranteze pătrate, indicând un interval. Nu este un metacaracter în regex, în afara parantezelor pătrate.

Negare

O clasă care include un interval poate fi negată. Adică, nimeni dintre personajele din set (clasă) nu trebuie să se potrivească. Acest lucru este indicat cu ^ metacharacter la începutul modelului clasei, imediat după paranteză pătrată de deschidere. Deci, [^ 0-9] înseamnă potrivirea caracterului la poziția corespunzătoare din țintă, care nu este niciun caracter din interval, de la 0 la 9 inclusiv. Deci, următorul cod nu va produce o potrivire:

dacă (regex_search(„0123456789101112”,regex(„[^ 0-9]”)))

cost<< „asortat” <<endl;

altceva

cost<< „nu se potrivește” <<endl;

O cifră în intervalul 0-9 poate fi găsită în oricare dintre pozițiile șirului țintă, 0123456789101112 ,; deci nu există nicio potrivire - negare.

Următorul cod produce o potrivire:

dacă (regex_search(„ABCDEFGHIJ”,regex(„[^ 0-9]”)))

cost<< „asortat” <<endl;

Nicio cifră nu a putut fi găsită în țintă, ABCDEFGHIJ ,; deci există un meci.

[a-z] este un interval în afara [^ a-z]. Și așa [^ a-z] este negația [a-z].

[A-Z] este un interval în afara [^ A-Z]. Și astfel [^ A-Z] este negația [A-Z].

Există alte negații.

Potrivirea spațiilor albe

‘’ Sau t sau r sau n sau f este un caracter de spațiu alb. În următorul cod, regex, n se potrivește cu „ n” din țintă:

dacă (regex_search(- De linia unu. r nDin rândul doi.,regex(' n')))

cost<< „asortat” <<endl;

Potrivire cu orice caracter al spațiului alb

Modelul sau clasa care se potrivește cu orice caracter din spațiul alb este, [ t r n f]. În următorul cod, „” se potrivește:

dacă (regex_search('unu doi',regex(„[ t r n f] ')))

cost<< „asortat” <<endl;

Potrivirea oricărui caracter non-spațiu

Modelul sau clasa care se potrivește cu orice caracter de spațiu care nu este alb este, [^ t r n f]. Următorul cod produce o potrivire deoarece nu există spațiu alb în țintă:

dacă (regex_search(„1234abcd”,regex('[^ t r n f] ')))

cost<< „asortat” <<endl;

Perioada (.) Din model

Punctul (.) Din model se potrivește cu orice caracter, inclusiv cu sine, cu excepția n, în țintă. O potrivire este produsă în următorul cod:

dacă (regex_search(„1234abcd”,regex('.')))

cost<< „asortat” <<endl;

Nu există rezultate potrivite în următorul cod, deoarece ținta este n.

dacă (regex_search(' n',regex('.')))

cost<< „asortat” <<endl;

altceva

cost<< „nu se potrivește” <<endl;

Notă: În interiorul unei clase de caractere cu paranteze pătrate, perioada nu are o semnificație specială.

Repetări potrivite

Un caracter sau un grup de caractere pot apărea de mai multe ori în șirul țintă. Un model se poate potrivi cu această repetare. Metacaractere,?, *, + Și {} sunt utilizate pentru a se potrivi cu repetarea din țintă. Dacă x este un caracter de interes în șirul țintă, atunci metacaractere au următoarele semnificații:

X*:înseamnă potrivire'X' 0sau de mai multe ori,eu.Și.,de câte ori

X+:înseamnă potrivire'X' 1sau de mai multe ori,eu.Și.,cel puțin o dată

X? :înseamnă potrivire'X' 0sau1 timp

X{n,}:înseamnă potrivire'X'cel puțin de n sau de mai multe ori.Notăvirgula.

X{n} :Meci'X'exact de n ori

X{n,m}:Meci'X'cel puțin de n ori,dar nu mai mult de m ori.

Aceste metacaractere sunt numite cuantificatoare.

Ilustrații

*

* Se potrivește cu caracterul precedent sau grupul precedent, de zero sau de mai multe ori. o * se potrivește cu „o” la câinele din șirul țintă. De asemenea, se potrivește cu oo în carte și în căutare. Regex, o * se potrivește cu boooo în Animalul cu booooed .. Notă: o * se potrivește cu dig, unde „o” are loc zero (sau mai mult) timp.

+

+ Corespunde caracterului precedent sau grupului precedent, de 1 sau mai multe ori. Contrastează-l cu zero sau de mai multe ori pentru *. Deci regexul, e + se potrivește cu „e” în mâncare, unde „e” apare o singură dată. e + se potrivește și cu ee la oi, unde „e” apare de mai multe ori. Notă: e + nu se va potrivi cu excavarea, deoarece în dig, „e” nu apare cel puțin o dată.

?

? se potrivește caracterului precedent sau grupului precedent, de 0 sau 1 dată (și nu mai mult). Deci, e? se potrivește săpare deoarece „e” apare în săpătură, timp zero. e? meciurile setate deoarece „e” apare în set, o singură dată. Notă: e? încă se potrivește cu oile; deși există două ‘e în oi. Există o nuanță aici - vezi mai târziu.

{n,}

Aceasta se potrivește cu cel puțin n repetări consecutive ale unui caracter sau grup precedent. Deci regexul, e {2,} se potrivește cu cele două „e în țintă, oaie și cu cele trei„ e în ținta oilor. e {2,} nu se potrivește setului, deoarece setul are un singur „e”.

{n}

Aceasta se potrivește exact cu n repetări consecutive ale unui caracter sau grup precedent. Deci regexul, e {2} se potrivește cu cele două „e” din țintă, oaie. e {2} nu se potrivește setului deoarece setul are un singur „e”. Ei bine, e {2} se potrivește cu două „e” în țintă, sheeep. Există o nuanță aici - vezi mai târziu.

{n, m}

Aceasta se potrivește cu mai multe repetări consecutive ale unui caracter precedent sau grup precedent, de oriunde de la n la m, inclusiv. Deci, e {1,3} nu se potrivește cu nimic în dig, care nu are „e”. Se potrivește cu cea „e” din set, cu cele două „e în oaie, cu cele trei„ e în oaie și cu trei „e în oaie. Există o nuanță la ultimul meci - vezi mai târziu.

Alternare potrivită

Luați în considerare următorul șir țintă din computer.

Ferma are porci de diferite dimensiuni.

Programatorul poate dori să știe dacă această țintă are capră, iepure sau porc. Codul ar fi după cum urmează:

charstr[] = „Ferma are porci de diferite dimensiuni.”;

dacă (regex_search(str,regex(„capră | iepure | porc”)))

cost<< „asortat” <<endl;

altceva

cost<< „nu se potrivește” <<endl;

Codul produce o potrivire. Rețineți utilizarea caracterului alternativ, |. Pot exista două, trei, patru și mai multe opțiuni. C ++ va încerca mai întâi să se potrivească cu prima alternativă, capra, la fiecare poziție de caractere din șirul țintă. Dacă nu reușește cu capra, încearcă următoarea alternativă, iepurele. Dacă nu reușește cu iepurele, încearcă următoarea alternativă, porcul. Dacă porcul eșuează, atunci C ++ trece la următoarea poziție în țintă și începe din nou cu prima alternativă.

În codul de mai sus, porcul este asociat.

Potrivirea începutul sau sfârșitul

Început


Dacă ^ este la începutul regexului, atunci textul de început al șirului țintă poate fi egalat cu regexul. În următorul cod, începutul țintei este abc, care se potrivește:

dacă (regex_search(„abc și def”,regex(„^ abc”)))

cost<< „asortat” <<endl;

Nu există nicio potrivire în următorul cod:

dacă (regex_search(„Da, abc și def”,regex(„^ abc”)))

cost<< „asortat” <<endl;

altceva

cost<< „nu se potrivește” <<endl;

Aici, abc nu se află la începutul țintei.

Notă: caracterul circumflex, „^”, este un metacaracter la începutul regexului, care se potrivește cu începutul șirului țintă. Este încă un metacaracter la începutul clasei de personaje, unde neagă clasa.

Sfârșit

Dacă $ se află la sfârșitul regexului, atunci textul final al șirului țintă poate fi egalat cu regexul. În următorul cod, sfârșitul țintei este xyz, care se potrivește:

dacă (regex_search(„uvw și xyz”,regex(„xyz $”)))

cost<< „asortat” <<endl;

Nu există nicio potrivire în următorul cod:

dacă (regex_search(„uvw și xyz final”,regex(„xyz $”)))

cost<< „asortat” <<endl;

altceva

cost<< „nu se potrivește” <<endl;

Aici, xyz nu se află la sfârșitul țintei.

Gruparea

Parantezele pot fi folosite pentru a grupa caractere într-un model. Luați în considerare următorul regex:

„un concert (pianist)”

Grupul de aici este pianist înconjurat de metacaractere (și). Este de fapt un subgrup, în timp ce un concert (pianist) este întregul grup. Luați în considerare următoarele:

„(Pianistul este bun)”

Aici, sub-grupul sau sub-coarda este, pianistul este bun.

Sub-șiruri cu părți comune

Un contabil este o persoană care are grijă de cărți. Imaginați-vă o bibliotecă cu un contabil și un raft. Să presupunem că una dintre următoarele șiruri țintă se află în computer:

„Biblioteca are un raft care este admirat.”;

„Iată contabilul.”;

„Contabilul lucrează cu raftul.”;

Să presupunem că interesul programatorului nu este să știe care dintre aceste propoziții se află în computer. Totuși, interesul său este să știe dacă raftul sau contabilul este prezent în orice șir țintă este în computer. În acest caz, regexul său poate fi:

„raft | contabil.”

Folosind alternanța.

Observați că această carte, care este comună pentru ambele cuvinte, a fost tastată de două ori, în cele două cuvinte din model. Pentru a evita tastarea cărții de două ori, regexul ar fi mai bine scris ca:

„carte (raft | deținător)”

Aici, grupul, raft | păstrător Metacaracterul alternativ a fost încă folosit, dar nu pentru două cuvinte lungi. A fost folosit pentru cele două părți de încheiere ale celor două cuvinte lungi. C ++ tratează un grup ca o entitate. Deci, C ++ va căuta raftul sau portarul care vine imediat după carte. Ieșirea următorului cod este potrivită:

charstr[] = „Biblioteca are un raft de cărți care este admirat.”;

dacă (regex_search(str,regex(„carte (raft | deținător)”)))

cost<< „asortat” <<endl;

raft și nu contabil au fost potrivite.

Icase și regex_constants multilinie

icase

Potrivirea este sensibilă la majuscule și minuscule. Cu toate acestea, poate fi făcută nesensibilă la majuscule. Pentru a realiza acest lucru, utilizați constanta regex :: icase, ca în următorul cod:

dacă (regex_search('Părere',regex('a hrani',regex::icase)))

cost<< „asortat” <<endl;

Ieșirea este potrivită. Așadar, Feedbackul cu „F” majuscul a fost asociat cu feedul cu „F” cu litere mici. regex :: icase a devenit al doilea argument al constructorului regex (). Fără asta, declarația nu ar produce un meci.

Multilinie

Luați în considerare următorul cod:

charstr[] = 'linia 1 nrandul 2 nlinia 3 ';

dacă (regex_search(str,regex('^. * $')))

cost<< „asortat” <<endl;

altceva

cost<< „nu se potrivește” <<endl;

Ieșirea nu este potrivită. Regexul, ^. * $, Se potrivește șirului țintă de la început până la sfârșit. . * înseamnă orice caracter cu excepția n, zero sau de mai multe ori. Deci, din cauza caracterelor newline ( n) din țintă, nu a existat nicio potrivire.

Ținta este un șir multiliniu. Pentru ca „.” Să se potrivească cu caracterul newline, trebuie să se facă constant regex :: multiline, al doilea argument al construcției regex (). Următorul cod ilustrează acest lucru:

charstr[] = 'linia 1 nrandul 2 nlinia 3 ';

dacă (regex_search(str,regex('^. * $',regex::multilinie)))

cost<< „asortat” <<endl;

altceva

cost<< „nu se potrivește” <<endl;

Potrivirea întregului șir țintă

Pentru a se potrivi întregului șir țintă, care nu are caracterul newline ( n), poate fi utilizată funcția regex_match (). Această funcție este diferită de regex_search (). Următorul cod ilustrează acest lucru:

charstr[] = 'primul, al doilea, al treilea';

dacă (regex_match(str,regex('.*al doilea.*')))

cost<< „asortat” <<endl;

Aici este un meci. Cu toate acestea, rețineți că regexul se potrivește cu întregul șir țintă, iar șirul țintă nu are nici un „ n”.

Obiectul match_results

Funcția regex_search () poate lua un argument între țintă și obiectul regex. Acest argument este obiectul match_results. Întreg șirul (parțial) asociat și sub-șirurile asortate pot fi cunoscute cu el. Acest obiect este o matrice specială cu metode. Tipul de obiect match_results este cmatch (pentru literele șirului).

Obținerea meciurilor

Luați în considerare următorul cod:

charstr[] = - Femeia pe care o căutați!;

cmatch m;

dacă (regex_search(str,m,regex(„w.m.n”)))

cost<<m[0] <<endl;

Șirul țintă are cuvântul femeie. Ieșirea este femeie ”, care corespunde regexului, w.m.n. La index zero, matricea specială deține singura potrivire, care este femeia.

Cu opțiunile de clasă, numai primul sub-șir găsit în țintă este trimis la matricea specială. Următorul cod ilustrează acest lucru:

cmatch m;

dacă (regex_search(- Șobolanul, pisica, liliacul!,m,regex(„[bcr] at”)))

cost<<m[0] <<endl;

cost<<m[1] <<endl;

cost<<m[2] <<endl;

Ieșirea este șobolan de la indexul zero. m [1] și m [2] sunt goale.

Cu alternative, numai primul sub-șir găsit în țintă este trimis la matricea specială. Următorul cod ilustrează acest lucru:

dacă (regex_search(- Iepurele, capra, porcul!,m,regex(„capră | iepure | porc”)))

cost<<m[0] <<endl;

cost<<m[1] <<endl;

cost<<m[2] <<endl;

Ieșirea este de iepure de la indexul zero. m [1] și m [2] sunt goale.

Grupări

Când sunt implicate grupuri, modelul complet se potrivește, intră în celula zero a matricei speciale. Următorul sub-șir găsit intră în celula 1; următorul șir, merge în celula 2; si asa mai departe. Următorul cod ilustrează acest lucru:

dacă (regex_search(„Cel mai bun librar de azi!”,m,regex(„carte ((sel) (ler))”)))

cost<<m[0] <<endl;

cost<<m[1] <<endl;

cost<<m[2] <<endl;

cost<<m[3] <<endl;

Ieșirea este:

librar

vânzător

celulă

citit

Rețineți că grupul (vânzătorul) vine înaintea grupului (sel).

Poziția meciului

Poziția potrivirii pentru fiecare sub-șir din matricea cmatch poate fi cunoscută. Numărarea începe de la primul caracter al șirului țintă, la poziția zero. Următorul cod ilustrează acest lucru:

cmatch m;

dacă (regex_search(„Cel mai bun librar de azi!”,m,regex(„carte ((sel) (ler))”)))

cost<<m[0] << '->' <<m.poziţie(0) <<endl;

cost<<m[1] << '->' <<m.poziţie(1) <<endl;

cost<<m[2] << '->' <<m.poziţie(2) <<endl;

cost<<m[3] << '->' <<m.poziţie(3) <<endl;

Rețineți utilizarea proprietății poziție, cu indicele celulei, ca argument. Ieșirea este:

librar->5

vânzător->9

celulă->9

citit->12

Căutați și înlocuiți

Un cuvânt sau o expresie nouă poate înlocui potrivirea. Funcția regex_replace () este utilizată pentru aceasta. Cu toate acestea, de data aceasta, șirul în care are loc înlocuirea este obiectul șir, nu șirul literal. Deci, biblioteca de șiruri trebuie inclusă în program. Ilustrare:

#include

#include

#include

folosind spațiul de nume std;

intprincipal()
{
str str= - Iată, vine omul meu. Uite omul tău.;
șir newStr=regex_replace(str,regex('om'), 'femeie');
cost<<newStr<<endl;

întoarcere 0;
}

Funcția regex_replace (), așa cum este codată aici, înlocuiește toate potrivirile. Primul argument al funcției este ținta, al doilea este obiectul regex, iar al treilea este șirul de înlocuire. Funcția returnează un șir nou, care este ținta, dar care înlocuiește. Ieșirea este:

Aici vine femeia mea. Uite femeia ta.

Concluzie

Expresia regulată folosește modele pentru a se potrivi cu șiruri de caractere din șirul de secvențe țintă. Modelele au metacaractere. Funcțiile utilizate în mod obișnuit pentru expresiile regulate C ++ sunt: ​​regex_search (), regex_match () și regex_replace (). O regex este un model în ghilimele duble. Cu toate acestea, aceste funcții iau obiectul regex ca argument și nu doar regex. Regexul trebuie transformat într-un obiect regex înainte ca aceste funcții să îl poată utiliza.