Ta niz je morda v računalniku in uporabnik bo morda želel vedeti, ali vsebuje besedo man. Če ima besedo moški, bo morda želel besedo moški spremeniti v žensko; tako da naj bi se niz glasil:
'Tukaj je moja ženska.'
Obstaja še veliko drugih želja, kot so te od uporabnika računalnika; nekateri so zapleteni. Regular Expression, skrajšano regex, je predmet obravnave teh težav z računalnikom. C ++ ima knjižnico z imenom regex. Torej, program C ++ za obravnavo regexa se mora začeti z:
#vključi
#vključi
z uporabo imenskega prostora std;
Ta članek pojasnjuje osnove pravilnega izražanja v C ++.
Vsebina članka
- Osnove rednega izražanja
- Vzorec
- Razredi znakov
- Ujemanje presledkov
- Obdobje (.) V vzorcu
- Ujemanje ponovitev
- Ujemanje alternacije
- Ujemanje začetka ali konca
- Združevanje
- Icase in multiline regex_constants
- Ujemanje celotnega cilja
- Objekt match_results
- Položaj tekme
- Išči in zamenjaj
- Zaključek
Osnove rednega izražanja
Regex
Vrvica, kot je Here is my man. zgoraj je ciljno zaporedje ali ciljni niz ali preprosto cilj. man, ki so ga iskali, je regularni izraz ali preprosto regex.
Ujemanje
Do ujemanja naj bi prišlo, ko se najde beseda ali stavek, ki ga iščete. Po ujemanju lahko pride do zamenjave. Na primer, potem ko se moški nahaja zgoraj, ga lahko nadomesti ženska.
Enostavno ujemanje
Naslednji program prikazuje, kako se beseda človek ujema.
#vključi
#vključi
z uporabo imenskega prostora std;
intglavni()
{
regex reg('človek');
če (regex_search('Tukaj je moj mož.',reg))
stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
vrnitev 0;
}
Funkcija regex_search () vrne true, če obstaja ujemanje in vrne false, če ni ujemanja. Tu funkcija sprejme dva argumenta: prvi je ciljni niz, drugi pa predmet regex. Regex je v dvojnih narekovajih 'človek'. Prvi stavek v funkciji main () tvori regex objekt. Regex je vrsta, reg pa predmet regex. Izhod zgornjega programa se 'ujema', saj je v ciljnem nizu viden 'man'. Če 'man' ni bil viden v cilju, bi regex_search () vrnil false, izhod pa bi bil 'not match'.
Izhod te kode se ne ujema:
regex reg('človek');če (regex_search('Tukaj je moje ustvarjanje.',reg))
stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Ni ujemanje, ker regexa 'man' ni mogoče najti v celotnem ciljnem nizu, 'Here is my making.'
Vzorec
Redni izraz, človek zgoraj, je zelo preprost. Regeksi običajno niso tako preprosti. Regularni izrazi imajo metaznake. Metaznaki so znaki s posebnim pomenom. Metaznak je lik o likih. Metaznaki regex C ++ so:
^$ .* + ? ( ) [ ] { } |Regex z ali brez metaznakov je vzorec.
Razredi znakov
Oglati oklepaji
Vzorec ima lahko znake v oglatih oklepajih. S tem bi se določeno mesto v ciljnem nizu ujemalo s katerim koli znakom v oglatih oklepajih. Upoštevajte naslednje cilje:
'Mačka je v sobi.''Netopir je v sobi.'
'Podgana je v sobi.'
Regex, [cbr] at bi se ujemal z mačko v prvi tarči. V drugi tarči bi se ujemal z netopirjem. Ujemal bi se s podgano v tretji tarči. To je zato, ker se mačka, netopir ali podgana začne z 'c' ali 'b' ali 'r'. Naslednji kodni segment to ponazarja:
regex reg('[cbr] ob');če (regex_search('Mačka je v sobi.',reg))
stroški<< 'ujeto' <<endl;
če (regex_search('Netopir je v sobi.',reg))
stroški<< 'ujeto' <<endl;
če (regex_search('Podgana je v sobi.',reg))
stroški<< 'ujeto' <<endl;
Izhod je:
ujemajoujemajo
ujemajo
Obseg znakov
Razred [cbr] v vzorcu [cbr] bi se ujemal z več možnimi znaki v tarči. To bi se ujemalo z 'c' ali 'b' ali 'r' v cilju. Če tarča nima nobenega od 'c' ali 'b' ali 'r', ki mu sledi at, ne bo ujemanja.
Nekatere možnosti, na primer 'c' ali 'b' ali 'r', obstajajo v razponu. Obseg števk od 0 do 9 ima 10 možnosti, vzorec za to pa je [0-9]. Obseg malih črk, od a do z, ima 26 možnosti, vzorec za to pa je [a-z]. Obseg velikih črk od A do Ž ima 26 možnosti, vzorec za to pa je [A-Z]. - uradno ni metaznak, vendar bi v oglatih oklepajih označeval obseg. Tako se ujema z naslednjim:
če (regex_search('ID6id',regex('[0-9]')))stroški<< 'ujeto' <<endl;
Upoštevajte, kako je bil regex zgrajen kot drugi argument. Ujema se med števko, 6 v razponu, od 0 do 9, in 6 v tarči, ID6id. Zgornja koda je enakovredna:
če (regex_search('ID6id',regex('[0123456789]')))stroški<< 'ujeto' <<endl;
Naslednja koda ustvari ujemanje:
charstr[] = 'ID6iE';če (regex_search(str,regex('[a-z]')))
stroški<< 'ujeto' <<endl;
Upoštevajte, da je prvi argument spremenljivka niza in ne literal niza. Ujemanje je med 'i' v [a-z] in 'i' v ID6iE.
Ne pozabite, da je obseg razred. Besedilo je lahko desno od obsega ali levo od obsega v vzorcu. Naslednja koda ustvari ujemanje:
če (regex_search('ID2id je osebna izkaznica ',regex('ID [0-9] id')))stroški<< 'ujeto' <<endl;
Ujema se med ID [0-9] id in ID2id. Preostanek ciljnega niza, je ID, se v tem primeru ne ujema.
Kot se uporablja v subjektu regularnega izraza (regexes), beseda class dejansko pomeni niz. To pomeni, da se eden od likov v nizu ujema.
Opomba: vezaj - je metaznak samo v oglatih oklepajih, ki označuje obseg. To ni metaznak v regularnem izrazu, izven oglatih oklepajev.
Negacija
Razred, ki vključuje obseg, je mogoče zanikati. To pomeni, da se noben od znakov v nizu (razredu) ne bi smel ujemati. To je označeno z metaznakom ^ na začetku vzorca razreda, tik za začetnim oglatim oklepajem. Torej [^0-9] pomeni ujemanje znaka na ustreznem mestu v tarči, ki ni kateri koli znak v obsegu, vključno od 0 do 9. Naslednja koda se torej ne bo ujemala:
če (regex_search('0123456789101112',regex('[^ 0-9]')))stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Številko v razponu od 0 do 9 je mogoče najti v katerem koli položaju ciljnega niza, 0123456789101112 ,; torej ni ujemanja - negacije.
Naslednja koda ustvari ujemanje:
če (regex_search('ABCDEFGHIJ',regex('[^ 0-9]')))stroški<< 'ujeto' <<endl;
V tarči ni bilo mogoče najti nobene številke, ABCDEFGHIJ ,; torej obstaja ujemanje.
[a-z] je obseg zunaj [^a-z]. In tako je [^a-z] negacija [a-z].
[A-Z] je območje zunaj [^A-Z]. In tako je [^A-Z] negacija [A-Z].
Obstajajo tudi druge negacije.
Ujemanje presledkov
‘’ Ali t ali r ali n ali f je presledek. V naslednji kodi se regex n ujema z ' n' v cilju:
če (regex_search('Prva vrstica. r nDruge vrstice. ',regex(' n')))stroški<< 'ujeto' <<endl;
Ujemanje s katerim koli presledkom
Vzorec ali razred, ki se ujema s katerim koli presledkom, je [ t r n f]. V naslednji kodi se ujema '':
če (regex_search('en dva',regex('[ t r n f] ')))stroški<< 'ujeto' <<endl;
Ujemanje s katerim koli znakom, ki ni prazen
Vzorec ali razred, ki se ujema s katerim koli znakom, ki ni prazen, je [^ t r n f]. Naslednja koda ustvari ujemanje, ker v cilju ni presledkov:
če (regex_search('1234abcd',regex('[^ t r n f] ')))stroški<< 'ujeto' <<endl;
Točka (.) V vzorcu
Točka (.) V vzorcu se ujema s katerim koli znakom, vključno s samim seboj, razen n, v cilju. Ujemanje se ustvari v naslednji kodi:
če (regex_search('1234abcd',regex('.')))stroški<< 'ujeto' <<endl;
V naslednji kodi ni ujemajočih se rezultatov, ker je cilj n.
če (regex_search(' n',regex('.')))stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Opomba: Znotraj razreda znakov s kvadratnimi oklepaji pika nima posebnega pomena.
Ujemanje ponovitev
Znak ali skupina znakov se lahko v ciljnem nizu pojavi več kot enkrat. Vzorec se lahko ujema s to ponovitvijo. Metaznaki,?, *, +In {} se uporabljajo za ujemanje ponavljanja v cilju. Če je x ciljni znak v ciljnem nizu, imajo metaznaki naslednji pomen:
x*:pomeni ujemanje'x' 0ali večkrat,jaz.In.,poljubno število kratx+:pomeni ujemanje'x' 1ali večkrat,jaz.In.,vsaj enkrat
x? :pomeni ujemanje'x' 0ali1 čas
x{n,}:pomeni ujemanje'x'vsaj n ali večkrat.Opombavejica.
x{n} :ujemati'x'točno n -krat
x{n,m}:ujemati'x'vsaj n krat,vendar ne več kot m krat.
Ti metaznaki se imenujejo količniki.
Ilustracije
*
* Se ujema s prejšnjim znakom ali prejšnjo skupino, nič ali večkrat. o* se ujema z 'o' v pasu ciljnega niza. Prav tako se ujema z oo v knjigi in iskanju. Regex, o* se ujema z boooo v Animal booooed .. Opomba: o* se ujema z dig, kjer se 'o' pojavi nič (ali več) časa.
+
+ Se ujema s prejšnjim znakom ali prejšnjo skupino, 1 ali večkrat. Primerjajte z ničlo ali večkrat za *. Tako se regex, e+ ujema z „e“ v prehrani, kjer se enkrat pojavi „e“. e+ se ujema tudi z ee pri ovcah, kjer se 'e' pojavlja večkrat. Opomba: e+ se ne bo ujemal z dig, ker se v dig 'e' ne pojavi vsaj enkrat.
?
The? se ujema s prejšnjim znakom ali prejšnjo skupino, 0 ali 1 -krat (in ne več). Torej, e? ujema dig, ker se v dig pojavi 'e', nič časa. e? se ujema, ker se v nizu enkrat pojavi »e«. Opomba: e? še vedno ustreza ovcam; čeprav sta pri ovcah dva 'e'. Tu je odtenek - glej kasneje.
{n,}
To ustreza najmanj n zaporednim ponovitvam predhodnega znaka ali prejšnje skupine. Tako se regex, e {2,} ujema z dvema „e“ v tarči, ovcami in tremi „e“ v ciljnem ovcu. e {2,} se ne ujema z nizom, ker ima niz samo eno 'e'.
{n}
To ustreza natanko n zaporednim ponovitvam predhodnega znaka ali prejšnje skupine. Tako se regex, e {2} ujema z dvema 'e' v tarči, ovce. e {2} se ne ujema z nizom, ker ima niz samo eno 'e'. No, e {2} se ujema z dvema 'e' v tarči, ovce. Tu je odtenek - glej kasneje.
{n, m}
To se ujema z več zaporednimi ponovitvami predhodnega znaka ali predhodne skupine, kjer koli od n do vključno vključno. Torej se e {1,3} nič ne ujema z dig, ki nima 'e'. Ujema se z enim 'e' v nizu, dvema 'e' v ovcah, tremi 'e' v ovcah in tremi 'e' v ovcah. Na zadnji tekmi je odtenek - glej kasneje.
Ujemanje alternacije
Razmislite o naslednjem ciljnem nizu v računalniku.
Na kmetiji so prašiči različnih velikosti.
Programer bo morda želel vedeti, ali ima ta tarča kozo, zajca ali prašiča. Koda bi bila naslednja:
charstr[] = 'Na kmetiji so prašiči različnih velikosti.';če (regex_search(str,regex('koza | zajec | prašič')))
stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Koda ustvari ujemanje. Upoštevajte uporabo znaka za zamenjavo, |. Možnosti so lahko dve, tri, štiri in več. C ++ se bo najprej poskušal ujemati s prvo alternativo, kozjo, na vsakem položaju znakov v ciljnem nizu. Če s kozo ne uspe, poskusi z naslednjo alternativo, zajcem. Če s kuncem ne uspe, poskusi z naslednjo alternativo, prašičem. Če prašič ne uspe, se C ++ premakne na naslednje mesto v tarči in znova začne s prvo alternativo.
V zgornji kodi se prašič ujema.
Ujemanje začetka ali konca
Začetek
Če je ^ na začetku regeksa, se lahko regex ujema z začetnim besedilom ciljnega niza. V naslednji kodi je začetek cilja abc, ki se ujema:
stroški<< 'ujeto' <<endl;
V naslednji kodi ni ujemanja:
če (regex_search('Da, abc in def',regex('^ abc')))stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Tu abc ni na začetku cilja.
Opomba: Circuflex znak '^' je metaznak na začetku regeksa, ki se ujema z začetkom ciljnega niza. Še vedno je metaznak na začetku razreda znakov, kjer razred zanika.
Konec
Če je $ na koncu regeksa, se lahko regex ujema s končnim besedilom ciljnega niza. V naslednji kodi je konec cilja xyz, ki se ujema:
če (regex_search('uvw in xyz',regex('xyz $')))stroški<< 'ujeto' <<endl;
V naslednji kodi ni ujemanja:
če (regex_search('uvw in xyz final',regex('xyz $')))stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Tukaj xyz ni na koncu cilja.
Združevanje
Oklepaji se lahko uporabljajo za združevanje znakov v vzorec. Upoštevajte naslednji regex:
'koncert (pianist)'Skupina je pianistka, obdana z metaznaki (in). Pravzaprav je podskupina, medtem ko je koncert (pianist) celotna skupina. Upoštevajte naslednje:
'(Pianist je dober)'Tu je podskupina ali podniz: pianist je dober.
Podniz z običajnimi deli
Knjigovodja je oseba, ki skrbi za knjige. Predstavljajte si knjižnico z knjigovodjo in knjižno polico. Predpostavimo, da je v računalniku eden od naslednjih ciljnih nizov:
'Knjižnica ima knjižno polico, ki jo občudujemo.';'Tukaj je knjigovodja.';
'Knjigovodja dela s knjižno polico.';
Predpostavimo, da programerjev interes ni vedeti, kateri od teh stavkov je v računalniku. Kljub temu ga zanima, ali je knjižna polica ali knjigovodja prisotna v katerem koli ciljnem nizu v računalniku. V tem primeru je njegov regex lahko:
'knjižna polica | knjigovodja.'Uporaba alternacije.
Upoštevajte, da je bila knjiga, ki je skupna obema besedama, dvakrat vtipkana v dveh besedah v vzorcu. Da se izognete dvakratnemu tipkanju knjige, bi bilo regex bolje zapisati tako:
'knjiga (polica | imetnik)'Tu je skupina, polica | imetnik nadomestnega metaznaka je bil še vedno uporabljen, vendar ne za dve dolgi besedi. Uporabljali so ga za dva zaključna dela dveh dolgih besed. C ++ obravnava skupino kot entiteto. Tako bo C ++ poiskal polico ali imetnika, ki pride takoj po knjigi. Izhod naslednje kode se ujema:
charstr[] = 'Knjižnica ima knjižno polico, ki jo občudujemo.';če (regex_search(str,regex('knjiga (polica | imetnik)')))
stroški<< 'ujeto' <<endl;
knjižna polica in ne knjigovodja sta se ujemala.
Icase in multiline regex_constants
icase
Ujemanje privzeto razlikuje velike in male črke. Lahko pa ga naredimo neobčutljivega na velike in male črke. Če želite to narediti, uporabite konstanto regex :: icase, kot v naslednji kodi:
če (regex_search('Povratne informacije',regex('krma',regex::icase)))stroški<< 'ujeto' <<endl;
Izhod se ujema. Tako se povratne informacije z velikimi črkami 'F' ujemajo z virom z malimi črkami 'f'. regex :: icase je bil drugi argument konstruktorja regex (). Brez tega se izjava ne bi ujemala.
Multiline
Upoštevajte naslednjo kodo:
charstr[] = 'vrstica 1 nvrstica 2 nvrstica 3 ';če (regex_search(str,regex('^. * $')))
stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Izhod se ne ujema. Regex, ^.*$, Se ujema s ciljnim nizom od začetka do konca. .* pomeni kateri koli znak razen n, nič ali večkrat. Tako zaradi znakov nove vrstice ( n) v cilju ni bilo ujemanja.
Cilj je večvrstični niz. Da bi se '.' Ujemalo z znakom nove vrstice, je treba narediti konstantno regex :: multiline, drugi argument konstrukcije regex (). Naslednja koda ponazarja to:
charstr[] = 'vrstica 1 nvrstica 2 nvrstica 3 ';če (regex_search(str,regex('^. * $',regex::večvrstično)))
stroški<< 'ujeto' <<endl;
drugače
stroški<< 'se ne ujema' <<endl;
Ujemanje niza celega cilja
Če želite ujemati celoten ciljni niz, ki nima znaka za novo vrstico ( n), lahko uporabite funkcijo regex_match (). Ta funkcija se razlikuje od regex_search (). Naslednja koda ponazarja to:
charstr[] = 'prvi drugi tretji';če (regex_match(str,regex('.*drugi.*')))
stroški<< 'ujeto' <<endl;
Tukaj je ujemanje. Vendar upoštevajte, da se regex ujema s celotnim ciljnim nizom, ciljni niz pa nima ' n'.
Objekt match_results
Funkcija regex_search () lahko sprejme argument med ciljem in predmetom regex. Ta argument je objekt match_results. Z njim je mogoče poznati celoten ujemajoči se del (del) in ujemajoče se nizove. Ta predmet je posebna matrika z metodami. Vrsta predmeta match_results je cmatch (za literale niza).
Pridobitev tekem
Upoštevajte naslednjo kodo:
charstr[] = 'Ženska, ki ste jo iskali!';cmatch m;
če (regex_search(str,m,regex('w.m.n')))
stroški<<m[0] <<endl;
Ciljni niz ima besedo ženska. Izhod je ženska, kar ustreza regularnemu izrazu, w.m.n. Pri indeksu nič ima posebna matrika edino ujemanje, to je ženska.
Z možnostmi razreda se v poseben niz pošlje samo prvi podniz, ki ga najdemo v cilju. Naslednja koda ponazarja to:
cmatch m;če (regex_search('Podgana, mačka, netopir!',m,regex('[bcr] pri')))
stroški<<m[0] <<endl;
stroški<<m[1] <<endl;
stroški<<m[2] <<endl;
Izhod je podgana iz indeksa nič. m [1] in m [2] sta prazna.
Z drugimi možnostmi se v prvi niz pošlje samo prvi podniz, ki ga najdemo v cilju. Naslednja koda ponazarja to:
če (regex_search('Zajec, koza, prašič!',m,regex('koza | zajec | prašič')))stroški<<m[0] <<endl;
stroški<<m[1] <<endl;
stroški<<m[2] <<endl;
Izhod je kunec iz indeksa nič. m [1] in m [2] sta prazna.
Združevanje v skupine
Ko so vključene skupine, se celoten vzorec ujema, gre v celico nič posebnega niza. Naslednji najdeni podniz je v celici 1; podniz, ki sledi, gre v celico 2; in tako naprej. Naslednja koda ponazarja to:
če (regex_search('Najboljši prodajalec knjig danes!',m,regex('book ((sel) (ler))')))stroški<<m[0] <<endl;
stroški<<m[1] <<endl;
stroški<<m[2] <<endl;
stroški<<m[3] <<endl;
Izhod je:
knjigarnaprodajalec
celica
prebrati
Upoštevajte, da je skupina (prodajalec) pred skupino (sel).
Položaj tekme
Položaj ujemanja za vsak podniz v nizu cmatch je lahko znan. Odštevanje se začne od prvega znaka ciljnega niza na položaju nič. Naslednja koda ponazarja to:
cmatch m;če (regex_search('Najboljši prodajalec knjig danes!',m,regex('book ((sel) (ler))')))
stroški<<m[0] << '->' <<mpoložaj(0) <<endl;
stroški<<m[1] << '->' <<mpoložaj(1) <<endl;
stroški<<m[2] << '->' <<mpoložaj(2) <<endl;
stroški<<m[3] << '->' <<mpoložaj(3) <<endl;
Upoštevajte uporabo lastnosti položaja z indeksom celic kot argument. Izhod je:
knjigarna->5prodajalec->9
celica->9
prebrati->12
Išči in zamenjaj
Nova beseda ali stavek lahko nadomesti ujemanje. Za to se uporablja funkcija regex_replace (). Tokrat pa je niz, kjer pride do zamenjave, nizni objekt, ne literal niza. Zato je treba knjižnico nizov vključiti v program. Ilustracija:
#vključi#vključi
#vključi
z uporabo imenskega prostora std;
intglavni()
{
niz str= 'Evo, prihaja moj mož. Tam gre vaš mož. ';
niz newStr=regex_replace(str,regex('človek'), 'ženska');
stroški<<novoStr<<endl;
vrnitev 0;
}
Funkcija regex_replace (), kot je kodirana tukaj, nadomešča vsa ujemanja. Prvi argument funkcije je cilj, drugi je predmet regex, tretji pa nadomestni niz. Funkcija vrne nov niz, ki je cilj, vendar ima zamenjavo. Izhod je:
Prihaja moja ženska. Tam gre tvoja ženska.
Zaključek
Regularni izraz uporablja vzorce za ujemanje podnizov v nizu ciljnega zaporedja. Vzorci imajo metaznake. Pogosto uporabljene funkcije za regularne izraze C ++ so: regex_search (), regex_match () in regex_replace (). Regex je vzorec v dvojnih narekovajih. Vendar te funkcije vzamejo predmet regex kot argument in ne le regex. Regex mora biti narejen v predmet regex, preden ga lahko te funkcije uporabijo.