Regular Expression Basics i C ++

Regular Expression Basics C



Tenk på følgende setning i sitater:

'Her er mannen min.'

Denne strengen kan være inne i datamaskinen, og brukeren vil kanskje vite om den har ordet mann. Hvis det har ordet mann, kan det være lurt å endre ordet mann til kvinne; slik at strengen skal lese:







'Her er kvinnen min.'

Det er mange andre ønsker som disse fra datamaskinbrukeren; noen er komplekse. Regular Expression, forkortet, regex, er gjenstand for håndtering av disse problemene av datamaskinen. C ++ kommer med et bibliotek som heter regex. Så et C ++ - program for å håndtere regex bør begynne med:



#inkludere

#inkludere

ved hjelp av navneområde std;

Denne artikkelen forklarer grunnleggende uttrykk for vanlig uttrykk i C ++.



Artikkelinnhold

Grunnleggende om vanlig uttrykk

Regex

En streng som Her er mannen min. ovenfor er målsekvensen eller målstrengen eller rett og slett målet. mann, som det ble søkt etter, er det vanlige uttrykket, eller ganske enkelt, regex.





Matchende

Matching sies å forekomme når ordet eller uttrykket som det søkes etter er funnet. Etter matchingen kan en erstatning finne sted. For eksempel, etter at mannen er plassert ovenfor, kan den erstattes av en kvinne.

Enkel matchning

Følgende program viser hvordan ordet mann matches.



#inkludere

#inkludere

ved hjelp av navneområde std;

inthoved-()
{

regex reg('Mann');
hvis (regex_search('Her er mannen min.',reg))
koste<< 'matchet' <<endl;
ellers
koste<< 'ikke matchet' <<endl;

komme tilbake 0;
}

Funksjonen regex_search () returnerer true hvis det er et samsvar og returnerer false hvis det ikke oppstår samsvar. Her tar funksjonen to argumenter: den første er målstrengen, og den andre er regex -objektet. Regexet i seg selv er 'mann', i doble anførselstegn. Den første setningen i hovedfunksjonen () danner regex -objektet. Regex er en type, og reg er regex -objektet. Programmet ovenfor er 'matchet', ettersom 'mann' er sett i målstrengen. Hvis 'mann' ikke ble sett i målet, ville regex_search () ha returnert usann, og utgangen ville ha blitt 'ikke matchet'.

Utdataene fra følgende kode samsvarer ikke:

regex reg('Mann');
hvis (regex_search('Her er min fremstilling.',reg))
koste<< 'matchet' <<endl;
ellers
koste<< 'ikke matchet' <<endl;

Ikke matchet fordi regex 'mannen' ikke ble funnet i hele målstrengen, 'Her er min fremstilling'.

Mønster

Det vanlige uttrykket, mannen ovenfor, er veldig enkelt. Regexes er vanligvis ikke så enkle. Vanlige uttrykk har metategn. Metakarakterer er tegn med spesielle betydninger. En metakarakter er et tegn om tegn. C ++ regex metategn er:

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

En regeks, med eller uten metategn, er et mønster.

Karakterklasser

Firkantede braketter

Et mønster kan ha tegn innenfor firkantede parenteser. Med dette vil en bestemt posisjon i målstrengen samsvare med noen av firkantparentesene. Vurder følgende mål:

'Katten er i rommet.'

'Flaggermusen er i rommet.'

'Rotten er i rommet.'

Regeksen, [cbr] at ville matche katten i det første målet. Det ville matche flaggermus i det andre målet. Det ville matche rotte i det tredje målet. Dette er fordi katt eller flaggermus eller rotte begynner med ‘c’ eller ‘b’ eller ‘r’. Følgende kodesegment illustrerer dette:

regex reg('[cbr] kl');
hvis (regex_search('Katten er i rommet.',reg))
koste<< 'matchet' <<endl;
hvis (regex_search('Flaggermusen er i rommet.',reg))
koste<< 'matchet' <<endl;
hvis (regex_search('Rotten er i rommet.',reg))
koste<< 'matchet' <<endl;

Utgangen er:

matchet

matchet

matchet

Utvalg av tegn

Klassen, [cbr] i mønsteret [cbr], ville matche flere mulige tegn i målet. Det ville matche 'c' eller 'b' eller 'r' i målet. Hvis målet ikke har noen av 'c' eller 'b' eller 'r', etterfulgt av kl, ville det ikke være noen treff.

Noen muligheter som 'c' eller 'b' eller 'r' finnes i et område. Sifferområdet, 0 til 9 har 10 muligheter, og mønsteret for det er [0-9]. Utvalget av små bokstaver, a til z, har 26 muligheter, og mønsteret for det er [a-z]. Utvalget av store bokstaver, A til Å, har 26 muligheter, og mønsteret for det er [A-Z]. - er ikke offisielt en metakarakter, men innenfor firkantede parenteser vil det indikere et område. Så følgende gir en kamp:

hvis (regex_search('ID6id',regex('[0-9]')))

koste<< 'matchet' <<endl;

Legg merke til hvordan regexet er konstruert som det andre argumentet. Matchen skjer mellom sifferet, 6 i området, 0 til 9, og 6 i målet, ID6id. Koden ovenfor tilsvarer:

hvis (regex_search('ID6id',regex('[0123456789]')))

koste<< 'matchet' <<endl;

Følgende kode gir et treff:

røyes[] = 'ID6iE';

hvis (regex_search(s,regex('[a-z]')))

koste<< 'matchet' <<endl;

Vær oppmerksom på at det første argumentet her er en strengvariabel og ikke strengen bokstavelig. Kampen er mellom ‘i’ i [a-z] og ‘i’ i ID6iE.

Ikke glem at et område er en klasse. Det kan være tekst til høyre for området eller til venstre for området i mønsteret. Følgende kode gir et treff:

hvis (regex_search('ID2id er en ID ',regex('ID [0-9] id')))

koste<< 'matchet' <<endl;

Kampen er mellom ID [0-9] id og ID2id. Resten av målstrengen, er en ID, samsvarer ikke i denne situasjonen.

Som det brukes i det vanlige uttrykksfaget (regekser), betyr ordklassen faktisk et sett. Det vil si at en av karakterene i settet er å matche.

Merk: bindestrek - er bare en metakarakter innenfor firkantede parenteser, som angir et område. Det er ikke en metakarakter i regekset, utenfor firkantparentesene.

Negasjon

En klasse som inkluderer en rekkevidde kan nektes. Det vil si at ikke noen av tegnene i settet (klassen) skal matche. Dette er indikert med ^ metakarakteren i begynnelsen av klassemønsteret, rett etter den åpne firkantparentesen. Så, [^0-9] betyr å matche tegnet på riktig posisjon i målet, som ikke er noe tegn i området, 0 til 9 inkluderende. Så følgende kode vil ikke produsere en kamp:

hvis (regex_search('0123456789101112',regex('[^ 0-9]')))

koste<< 'matchet' <<endl;

ellers

koste<< 'ikke matchet' <<endl;

Et siffer innenfor området 0 til 9 kan bli funnet i hvilken som helst av målstrengposisjonene, 0123456789101112 ,; så det er ingen match - negasjon.

Følgende kode gir et treff:

hvis (regex_search('ABCDEFGHIJ',regex('[^ 0-9]')))

koste<< 'matchet' <<endl;

Ingen siffer ble funnet i målet, ABCDEFGHIJ ,; så det er en kamp.

[a-z] er et område utenfor [^a-z]. Og så er [^a-z] negasjonen av [a-z].

[A-Z] er et område utenfor [^A-Z]. Og så er [^A-Z] negasjonen av [A-Z].

Andre negasjoner eksisterer.

Matchende mellomrom

‘’ Eller t eller r eller n eller f er et mellomromstegn. I den følgende koden samsvarer regexet, n med ‘ n’ i målet:

hvis (regex_search('Av linje en. r nAv linje to. ',regex(' n')))

koste<< 'matchet' <<endl;

Matcher alle mellomromstegn

Mønsteret eller klassen som skal matche et hvilket som helst mellomromstegn er [ t r n f]. I følgende kode samsvarer ‘’:

hvis (regex_search('en to',regex('[ t r n f] ')))

koste<< 'matchet' <<endl;

Matcher alle ikke-hvite mellomromstegn

Mønsteret eller klassen som skal matche et ikke-hvitt mellomromstegn er [^ t r n f]. Følgende kode gir en treff fordi det ikke er mellomrom i målet:

hvis (regex_search('1234abcd',regex('[^ t r n f] ')))

koste<< 'matchet' <<endl;

Perioden (.) I mønsteret

Perioden (.) I mønsteret samsvarer med alle tegn som inkluderer seg selv, unntatt n, i målet. En kamp er produsert i følgende kode:

hvis (regex_search('1234abcd',regex('.')))

koste<< 'matchet' <<endl;

Ingen samsvarer med følgende kode fordi målet er n.

hvis (regex_search(' n',regex('.')))

koste<< 'matchet' <<endl;

ellers

koste<< 'ikke matchet' <<endl;

Merk: Inne i en tegnklasse med firkantede parenteser har perioden ingen spesiell betydning.

Matchende gjentakelser

Et tegn eller en gruppe tegn kan forekomme mer enn én gang i målstrengen. Et mønster kan matche denne repetisjonen. Metategnene,?, *, +Og {} brukes for å matche gjentakelsen i målet. Hvis x er et tegn av interesse i målstrengen, har metategnene følgende betydninger:

x*:betyr match'x' 0eller flere ganger,Jeg.Og.,et hvilket som helst antall ganger

x+:betyr match'x' 1eller flere ganger,Jeg.Og.,i hvert fall en gang

x? :betyr match'x' 0eller1 tid

x{n,}:betyr match'x'minst n eller flere ganger.Merkkommaet.

x{n} :kamp'x'nøyaktig n ganger

x{n,m}:kamp'x'minst n ganger,men ikke mer enn m ganger.

Disse metategnene kalles kvantifiserere.

Illustrasjoner

*

* Samsvarer med forrige tegn eller foregående gruppe, null eller flere ganger. o* matcher ‘o’ i hunden til målstrengen. Det matcher også oo i bok og utseende. Regeksen, o* matcher boooo i Dyret booooed .. Merk: o* matches dig, der ‘o’ forekommer null (eller mer) tid.

+

+ Samsvarer med forrige tegn eller foregående gruppe, 1 eller flere ganger. Kontrast det med null eller flere ganger for *. Så regex, e+ matcher ‘e’ i spise, der ‘e’ forekommer en gang. e+ matcher også ee hos sauer, der ‘e’ forekommer mer enn én gang. Merk: e+ vil ikke samsvare med dig fordi i gra forekommer ‘e’ ikke minst én gang.

?

Den? samsvarer med forrige tegn eller foregående gruppe, 0 eller 1 gang (og ikke mer). Så, e? fyrstikker graver fordi ‘e’ forekommer i graven, null tid. e? matcher satt fordi ‘e’ forekommer i sett, én gang. Merk: e? matcher fortsatt sauer; selv om det er to ‘e’er hos sauer. Det er en nyanse her - se senere.

{n,}

Dette samsvarer med minst n gjentatte repetisjoner av et foregående tegn eller en foregående gruppe. Så regeksen, e {2,} matcher de to ‘e’ene i målet, sauene, og de tre‘ e’ene i målsauen. e {2,} samsvarer ikke med settet, fordi settet bare har én ‘e’.

{n}

Dette samsvarer nøyaktig med n gjentatte repetisjoner av et foregående tegn eller en foregående gruppe. Så regex, e {2} matcher de to ‘e’ene i målet, sau. e {2} samsvarer ikke med settet fordi settet bare har én ‘e’. Vel, e {2} matcher to ‘e’er i målet, saue. Det er en nyanse her - se senere.

{n, m}

Dette samsvarer med flere påfølgende repetisjoner av en foregående karakter eller foregående gruppe, alt fra n til m, inkludert. Så e {1,3} matcher ingenting i dig, som ikke har noen ‘e’. Den matcher den ene ‘e’ i settet, de to ‘e’ene hos sauer, de tre‘ e’ene i saue og tre ‘e’ene i sheeeep. Det er en nyanse ved den siste kampen - se senere.

Matchende alternativ

Vurder følgende målstreng på datamaskinen.

Gården har griser i forskjellige størrelser.

Programmereren vil kanskje vite om dette målet har geit eller kanin eller gris. Koden vil være som følger:

røyes[] = 'Gården har griser i forskjellige størrelser.';

hvis (regex_search(s,regex('geit | kanin | gris')))

koste<< 'matchet' <<endl;

ellers

koste<< 'ikke matchet' <<endl;

Koden gir en kamp. Legg merke til bruken av vekslingstegnet,. Det kan være to, tre, fire og flere alternativer. C ++ vil først prøve å matche det første alternativet, geit, på hver tegnposisjon i målstrengen. Hvis det ikke lykkes med geit, prøver det det neste alternativet, kanin. Hvis det ikke lykkes med kanin, prøver det det neste alternativet, gris. Hvis grisen mislykkes, går C ++ videre til neste posisjon i målet og starter med det første alternativet igjen.

I koden ovenfor er gris matchet.

Matchende begynnelse eller slutt

Begynnelse


Hvis ^ er i begynnelsen av regexet, kan begynnelsesteksten til målstrengen matches med regexet. I den følgende koden er starten på målet abc, som matches:

hvis (regex_search('abc og def',regex('^ abc')))

koste<< 'matchet' <<endl;

Ingen matching finner sted i følgende kode:

hvis (regex_search('Ja, abc og def',regex('^ abc')))

koste<< 'matchet' <<endl;

ellers

koste<< 'ikke matchet' <<endl;

Her er abc ikke i begynnelsen av målet.

Merk: Circumflex -tegnet, ‘^’, er en metakarakter i begynnelsen av regex, som samsvarer med starten på målstrengen. Det er fortsatt en metakarakter i begynnelsen av karakterklassen, der den negerer klassen.

Slutt

Hvis $ er på slutten av regexet, kan slutteksten til målstrengen matches med regexet. I den følgende koden er slutten av målet xyz, som matches:

hvis (regex_search('uvw og xyz',regex('xyz $')))

koste<< 'matchet' <<endl;

Ingen matching finner sted i følgende kode:

hvis (regex_search('uvw og xyz final',regex('xyz $')))

koste<< 'matchet' <<endl;

ellers

koste<< 'ikke matchet' <<endl;

Her er xyz ikke på slutten av målet.

Gruppering

Parenteser kan brukes til å gruppere tegn i et mønster. Vurder følgende regeks:

'en konsert (pianist)'

Gruppen her er pianist omgitt av metakarakterene (og). Det er faktisk en undergruppe, mens en konsert (pianist) er hele gruppen. Vurder følgende:

'(Pianisten er god)'

Her er undergruppen eller understrengen, pianist er bra.

Delstrenger med vanlige deler

En bokholder er en person som tar seg av bøker. Tenk deg et bibliotek med en bokholder og bokhylle. Anta at en av følgende målstrenger er i datamaskinen:

'Biblioteket har en bokhylle som beundres.';

'Her er bokføreren.';

'Bokføreren jobber med bokhyllen.';

Anta at programmererens interesse ikke er å vite hvilken av disse setningene som er i datamaskinen. Likevel er interessen hans å vite om bokhylle eller bokholder er tilstede i hvilken målstreng som er i datamaskinen. I dette tilfellet kan regexet hans være:

'bokhylle | bokholder.'

Bruker veksling.

Legg merke til at boken, som er felles for begge ordene, har blitt skrevet to ganger, i de to ordene i mønsteret. For å unngå å skrive bok to ganger, ville regeksen være bedre skrevet som:

'bok (hylle | keeper)'

Her er gruppen, hyllen | keeper Den alternative metakarakteren har fremdeles blitt brukt, men ikke for to lange ord. Den har blitt brukt for de to sluttdelene av de to lange ordene. C ++ behandler en gruppe som en enhet. Så, C ++ vil lete etter en hylle eller beholder som kommer umiddelbart etter boken. Utdataene fra følgende kode samsvarer:

røyes[] = 'Biblioteket har en bokhylle som beundres.';

hvis (regex_search(s,regex('bok (hylle | keeper)')))

koste<< 'matchet' <<endl;

bokhylle og ikke bokholder har blitt matchet.

Icase og multiline regex_constants

icase

Matching er som standard skift mellom store og små bokstaver. Det kan imidlertid gjøres ufølsomt for store og små bokstaver. For å oppnå dette, bruk regex :: icase -konstanten, som i følgende kode:

hvis (regex_search('Tilbakemelding',regex('mate',regex::icase)))

koste<< 'matchet' <<endl;

Utgangen samsvarer. Så tilbakemelding med store 'F' har blitt matchet med feed med små 'f'. regex :: icase er blitt det andre argumentet til regex () -konstruktøren. Uten det ville uttalelsen ikke produsert en match.

Multiline

Vurder følgende kode:

røyes[] = 'linje 1 nlinje 2 nlinje 3 ';

hvis (regex_search(s,regex('^. * $')))

koste<< 'matchet' <<endl;

ellers

koste<< 'ikke matchet' <<endl;

Utgangen samsvarer ikke. Regekset, ^.*$, Samsvarer med målstrengen fra begynnelsen til slutten. .* betyr ethvert tegn unntatt n, null eller flere ganger. Så på grunn av nylinjetegnene ( n) i målet var det ingen samsvar.

Målet er en flerlinjes streng. For at ‘.’ Skal matche newline -tegnet, må det konstante regex :: multiline lages, det andre argumentet for regex () -konstruksjonen. Følgende kode illustrerer dette:

røyes[] = 'linje 1 nlinje 2 nlinje 3 ';

hvis (regex_search(s,regex('^. * $',regex::flerlinjes)))

koste<< 'matchet' <<endl;

ellers

koste<< 'ikke matchet' <<endl;

Matcher hele målstrengen

For å matche hele målstrengen, som ikke har newline -tegnet ( n), kan funksjonen regex_match () brukes. Denne funksjonen er forskjellig fra regex_search (). Følgende kode illustrerer dette:

røyes[] = 'første andre tredje';

hvis (regex_match(s,regex('.*sekund.*')))

koste<< 'matchet' <<endl;

Det er en kamp her. Vær imidlertid oppmerksom på at regexet samsvarer med hele målstrengen, og målstrengen ikke har noen ‘ n’.

Match_results -objektet

Regex_search () -funksjonen kan ta et argument mellom målet og regex-objektet. Dette argumentet er match_results -objektet. Hele den matchede (del) strengen og delstrengene som matches kan kjennes med den. Dette objektet er et spesielt utvalg med metoder. Objekttypen match_results er cmatch (for strenglitteraler).

Få kamper

Vurder følgende kode:

røyes[] = 'Kvinnen du lette etter!';

cmatch m;

hvis (regex_search(s,m,regex('w.m.n')))

koste<<m[0] <<endl;

Målstrengen har ordet kvinne. Utgangen er kvinne ’, som tilsvarer regex, w.m.n. Ved indeks null holder den spesielle matrisen den eneste kampen, som er kvinne.

Med klassealternativer blir bare den første delstrengen som finnes i målet, sendt til den spesielle matrisen. Følgende kode illustrerer dette:

cmatch m;

hvis (regex_search('Rotta, katten, flaggermusen!',m,regex('[bcr] kl')))

koste<<m[0] <<endl;

koste<<m[1] <<endl;

koste<<m[2] <<endl;

Utgangen er rotte fra indeks null. m [1] og m [2] er tomme.

Med alternativer blir bare den første delstrengen som finnes i målet, sendt til den spesielle matrisen. Følgende kode illustrerer dette:

hvis (regex_search('Kaninen, bukken, grisen!',m,regex('geit | kanin | gris')))

koste<<m[0] <<endl;

koste<<m[1] <<endl;

koste<<m[2] <<endl;

Utgangen er kanin fra indeks null. m [1] og m [2] er tomme.

Grupperinger

Når grupper er involvert, går det komplette mønsteret inn i celle null i den spesielle matrisen. Den neste understrengen som blir funnet, går inn i celle 1; delstrengen som følger, går inn i celle 2; og så videre. Følgende kode illustrerer dette:

hvis (regex_search('Beste bokhandler i dag!',m,regex('bok ((sel) (ler))')))

koste<<m[0] <<endl;

koste<<m[1] <<endl;

koste<<m[2] <<endl;

koste<<m[3] <<endl;

Utgangen er:

bokhandler

selger

celle

lese

Vær oppmerksom på at gruppen (selger) kommer før gruppen (sel).

Kampens posisjon

Matchingsposisjonen for hver delstreng i cmatch-matrisen kan være kjent. Tellingen begynner fra det første tegnet i målstrengen, ved posisjon null. Følgende kode illustrerer dette:

cmatch m;

hvis (regex_search('Beste bokhandler i dag!',m,regex('bok ((sel) (ler))')))

koste<<m[0] << '->' <<m.posisjon(0) <<endl;

koste<<m[1] << '->' <<m.posisjon(1) <<endl;

koste<<m[2] << '->' <<m.posisjon(2) <<endl;

koste<<m[3] << '->' <<m.posisjon(3) <<endl;

Legg merke til bruken av posisjonsegenskapen, med celleindeksen, som et argument. Utgangen er:

bokhandler->5

selger->9

celle->9

lese->12

Søk og erstatt

Et nytt ord eller en setning kan erstatte kampen. Regex_replace () -funksjonen brukes til dette. Denne gangen er imidlertid strengen der erstatningen skjer, strengobjektet, ikke strengen bokstavelig. Så strengbiblioteket må inkluderes i programmet. Illustrasjon:

#inkludere

#inkludere

#inkludere

ved hjelp av navneområde std;

inthoved-()
{
streng str= 'Her kommer mannen min. Der går mannen din. ';
streng newStr=regex_replace(s,regex('Mann'), 'kvinne');
koste<<newStr<<endl;

komme tilbake 0;
}

Regex_replace () -funksjonen, som kodet her, erstatter alle treff. Det første argumentet for funksjonen er målet, det andre er regex -objektet, og det tredje er erstatningsstrengen. Funksjonen returnerer en ny streng, som er målet, men som har erstatningen. Utgangen er:

Her kommer kvinnen min. Der går kvinnen din.

Konklusjon

Det vanlige uttrykket bruker mønstre for å matche underlag i målsekvensstrengen. Mønstre har metategn. Vanlige funksjoner for C ++ regulære uttrykk, er: regex_search (), regex_match () og regex_replace (). En regeks er et mønster i doble anførselstegn. Imidlertid tar disse funksjonene regex -objektet som et argument og ikke bare regex. Regexet må gjøres til et regex -objekt før disse funksjonene kan bruke det.