Regular Expression Basics i C ++

Regular Expression Basics C



Overvej følgende sætning i citater:

'Her er min mand.'

Denne streng kan være inde i computeren, og brugeren vil måske vide, om den har ordet mand. Hvis det har ordet mand, vil han så måske gerne ændre ordet mand til kvinde; så strengen skulle læse:







'Her er min kvinde.'

Der er mange andre ønsker som disse fra computerbrugeren; nogle er komplekse. Regular Expression, forkortet, regex, er genstand for håndtering af disse problemer af computeren. C ++ leveres med et bibliotek kaldet regex. Så et C ++ - program til håndtering af regex bør begynde med:



#omfatte

#omfatte

ved hjælp af navneområde std;

Denne artikel forklarer grundlæggende regler for regulær ekspression i C ++.



Artikelindhold

Grundlæggende regler for regulær udtryk

Regex

En snor som Her er min mand. ovenfor er målsekvensen eller målstrengen eller simpelthen mål. mand, som blev søgt efter, er det regulære udtryk eller simpelthen regex.





Matchende

Matchning siges at forekomme, når det ord eller den sætning, der søges efter, er fundet. Efter matchning kan en udskiftning finde sted. For eksempel, efter at manden er placeret ovenfor, kan den erstattes af en kvinde.

Enkel matchning

Følgende program viser, hvordan ordet mand matches.



#omfatte

#omfatte

ved hjælp af navneområde std;

intvigtigste()
{

regex reg('mand');
hvis (regex_search('Her er min mand.',reg))
koste<< 'matchet' <<endl;
andet
koste<< 'ikke matchet' <<endl;

Vend tilbage 0;
}

Funktionen regex_search () returnerer true, hvis der er et match og returnerer false, hvis der ikke finder nogen match. Her tager funktionen to argumenter: den første er målstrengen, og den anden er regex -objektet. Selve regexet er 'mand', i dobbelte citater. Den første sætning i hovedfunktionen () danner regex -objektet. Regex er en type, og reg er regex -objektet. Ovenstående programs output er 'matchet', da 'man' ses i målstrengen. Hvis 'mand' ikke blev set i målet, ville regex_search () have returneret falsk, og output ville have været 'ikke matchet'.

Outputtet af følgende kode matches ikke:

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

Matches ikke, fordi regex 'mand' ikke kunne findes i hele målstrengen, 'Her er min fremstilling'.

Mønster

Det almindelige udtryk, mennesket ovenfor, er meget enkelt. Regexes er normalt ikke så enkle. Regelmæssige udtryk har metategn. Metategn er tegn med særlige betydninger. En metakarakter er et tegn om tegn. C ++ regex -metategn er:

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

Et regex, med eller uden metategn, er et mønster.

Karakterklasser

Firkantede beslag

Et mønster kan have tegn inden for parenteser. Med dette ville en bestemt position i målstrengen matche enhver af de firkantede parentesers tegn. Overvej følgende mål:

'Katten er i rummet.'

'Flagermusen er i rummet.'

'Rotten er i rummet.'

Regex, [cbr] at ville matche kat i det første mål. Det ville matche flagermus i det andet mål. Det ville matche rotte i det tredje mål. Dette skyldes, at kat eller flagermus eller rotte begynder med 'c' eller 'b' eller 'r'. Følgende kodesegment illustrerer dette:

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

Outputtet er:

matchede

matchede

matchede

Serie af 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 nogen af ​​'c' eller 'b' eller 'r' efterfulgt af kl, ville der ikke være nogen match.

Nogle muligheder som 'c' eller 'b' eller 'r' findes i et område. Cifreområdet, 0 til 9 har 10 muligheder, og mønsteret for det er [0-9]. Sortimentet af små alfabeter, a til z, har 26 muligheder, og mønsteret for det er [a-z]. Sortimentet af store bogstaver, A til Z, har 26 muligheder, og mønsteret for det er [A-Z]. - er ikke officielt en metakarakter, men inden for firkantede parenteser ville det angive et område. Så følgende producerer et match:

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

koste<< 'matchet' <<endl;

Bemærk hvordan regex er blevet konstrueret som det andet argument. Matchen finder sted mellem cifret, 6 i området, 0 til 9 og 6 i målet, ID6id. Ovenstående kode svarer til:

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

koste<< 'matchet' <<endl;

Følgende kode producerer et match:

forkælelses[] = 'ID6iE';

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

koste<< 'matchet' <<endl;

Bemærk, at det første argument her er en strengvariabel og ikke strengen bogstavelig. Kampen er mellem 'i' i [a-z] og 'i' i ID6iE.

Glem ikke, at en rækkevidde er en klasse. Der kan være tekst til højre for området eller til venstre for området i mønsteret. Følgende kode producerer et match:

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

koste<< 'matchet' <<endl;

Matchen er mellem ID [0-9] id og ID2id. Resten af ​​målstrengen, er et ID, matches ikke i denne situation.

Som det bruges i det regulære udtryksemne (regexes), betyder ordklassen faktisk et sæt. Det vil sige, at en af ​​figurerne i sættet er at matche.

Bemærk: bindestreg - er kun en metakarakter inden for firkantede parenteser, hvilket angiver et område. Det er ikke en metakarakter i regex uden for firkantede parenteser.

Negation

En klasse inklusive en rækkevidde kan negeres. Det vil sige, at ikke en af ​​tegnene i sættet (klassen) skal matche. Dette er angivet med ^ metakarakteren i begyndelsen af ​​klassemønsteret, lige efter den åbende firkant. Så [^0-9] betyder at matche tegnet på den passende position i målet, hvilket ikke er noget tegn i området, 0 til 9 inklusive. Så følgende kode vil ikke producere et match:

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

koste<< 'matchet' <<endl;

andet

koste<< 'ikke matchet' <<endl;

Et ciffer inden for området 0 til 9 kunne findes i enhver af målstrengpositionerne, 0123456789101112 ,; så der er ingen match - negation.

Følgende kode producerer et match:

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

koste<< 'matchet' <<endl;

Der kunne ikke findes et ciffer i målet, ABCDEFGHIJ ,; så der er en match.

[a-z] er et område uden for [^a-z]. Og så er [^a-z] negationen af ​​[a-z].

[A-Z] er et område uden for [^A-Z]. Og så er [^A-Z] negationen af ​​[A-Z].

Andre negationer findes.

Matchende mellemrum

‘’ Eller t eller r eller n eller f er et mellemrumstegn. I den følgende kode matcher regex, n ‘ n’ i målet:

hvis (regex_search('Af linje et. r nAf linje to. ',regex(' n')))

koste<< 'matchet' <<endl;

Matcher enhver Whitespace -karakter

Mønsteret eller klassen, der matcher ethvert hvidt mellemrumstegn, er [ t r n f]. I den følgende kode matches ‘’:

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

koste<< 'matchet' <<endl;

Matcher enhver ikke-hvidtegnet karakter

Mønsteret eller klassen, der matcher et ikke-hvidt mellemrumstegn, er [^ t r n f]. Følgende kode producerer et match, fordi der ikke er noget mellemrum i målet:

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

koste<< 'matchet' <<endl;

Perioden (.) I Mønsteret

Perioden (.) I mønsteret matcher ethvert tegn inklusive sig selv, undtagen n, i målet. En kamp produceres i følgende kode:

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

koste<< 'matchet' <<endl;

Ingen matchende resultater resulterer i følgende kode, fordi målet er n.

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

koste<< 'matchet' <<endl;

andet

koste<< 'ikke matchet' <<endl;

Bemærk: Inde i en tegnklasse med firkantede parenteser har perioden ingen særlig betydning.

Matchende gentagelser

Et tegn eller en gruppe af tegn kan forekomme mere end én gang inden for målstrengen. Et mønster kan matche denne gentagelse. Metategnene,?, *, +Og {} bruges til at matche gentagelsen i målet. Hvis x er et tegn af interesse i målstrengen, har metategnene følgende betydninger:

x*:betyder match'x' 0eller flere gange,jeg.Og.,et vilkårligt antal gange

x+:betyder match'x' 1eller flere gange,jeg.Og.,mindst en gang

x? :betyder match'x' 0eller1 tid

x{n,}:betyder match'x'mindst n eller flere gange.Bemærkkommaet.

x{n} :match'x'nøjagtig n gange

x{n,m}:match'x'mindst n gange,men ikke mere end m gange.

Disse metakarakterer kaldes kvantificatorer.

Illustrationer

*

* Matcher det foregående tegn eller den foregående gruppe, nul eller flere gange. o* matcher ‘o’ i hunden i målstrengen. Det matcher også oo i bog og udseende. Regexet, o* matcher boooo i Dyret booooed .. Bemærk: o* matches dig, hvor ‘o’ forekommer nul (eller mere) tid.

+

+ Matcher det foregående tegn eller den foregående gruppe, 1 eller flere gange. Kontrast det med nul eller flere gange for *. Så regex, e+ matcher 'e' i spise, hvor 'e' forekommer en gang. e+ matcher også ee hos får, hvor ‘e’ forekommer mere end én gang. Bemærk: e+ matcher ikke dig, fordi i dig forekommer 'e' ikke mindst én gang.

?

Det ? matcher det foregående tegn eller den foregående gruppe, 0 eller 1 gang (og ikke mere). Så, e? kampe graver, fordi 'e' forekommer i graven, nul tid. e? match sæt, fordi 'e' forekommer i sæt, én gang. Bemærk: e? matcher stadig får; selvom der er to ’e’er i får. Der er en nuance her - se senere.

{n,}

Dette matcher mindst n på hinanden følgende gentagelser af et foregående tegn eller en foregående gruppe. Så regex, e {2,} matcher de to ‘e’er i målet, får og de tre‘ e’er i måleskapen. e {2,} matcher ikke sæt, fordi sæt kun har ét ’e’.

{n}

Dette matcher nøjagtigt n på hinanden følgende gentagelser af et foregående tegn eller en foregående gruppe. Så regex, e {2} matcher de to ’e’er i målet, får. e {2} matcher ikke sæt, fordi sættet kun har ét ’e’. Tja, e {2} matcher to ’e’er i målet, sheep. Der er en nuance her - se senere.

{n, m}

Dette matcher flere på hinanden følgende gentagelser af en foregående karakter eller foregående gruppe, alt fra n til m, inklusive. Så e {1,3} matcher intet i dig, som ikke har ’e’. Det matcher det ene ‘e’ i sættet, de to ‘e’er i får, de tre‘ e’er i sheep og tre ‘e’er i sheeeep. Der er en nuance ved den sidste kamp - se senere.

Matchende skifte

Overvej følgende målstreng i computeren.

Gården har grise i forskellige størrelser.

Programmereren vil måske vide, om dette mål har ged eller kanin eller gris. Koden ville være som følger:

forkælelses[] = 'Gården har grise i forskellige størrelser.';

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

koste<< 'matchet' <<endl;

andet

koste<< 'ikke matchet' <<endl;

Koden producerer et match. Bemærk brugen af ​​vekslingstegnet, |. Der kan være to, tre, fire og flere muligheder. C ++ vil først prøve at matche det første alternativ, ged, ved hver karakterposition i målstrengen. Hvis det ikke lykkes med ged, forsøger det det næste alternativ, kanin. Hvis det ikke lykkes med kanin, prøver det det næste alternativ, gris. Hvis grisen mislykkes, går C ++ videre til den næste position i målet og starter med det første alternativ igen.

I ovenstående kode matches svin.

Matchende begyndelse eller slutning

Starten


Hvis ^ er i begyndelsen af ​​regex, kan startteksten i målstrengen matches med regexet. I den følgende kode er starten på målet abc, som matches:

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

koste<< 'matchet' <<endl;

Ingen matchning finder sted i følgende kode:

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

koste<< 'matchet' <<endl;

andet

koste<< 'ikke matchet' <<endl;

Her er abc ikke i begyndelsen af ​​målet.

Bemærk: Circumflex -tegnet, ‘^’, er en metakarakter i starten af ​​regexet, der matcher starten af ​​målstrengen. Det er stadig en metakarakter i starten af ​​karakterklassen, hvor den negerer klassen.

Ende

Hvis $ er i slutningen af ​​regex, kan slutteksten for målstrengen matches med regexet. I den følgende kode er slutningen af ​​målet xyz, som matches:

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

koste<< 'matchet' <<endl;

Ingen matchning finder sted i følgende kode:

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

koste<< 'matchet' <<endl;

andet

koste<< 'ikke matchet' <<endl;

Her er xyz ikke i slutningen af ​​målet.

Gruppering

Parenteser kan bruges til at gruppere tegn i et mønster. Overvej følgende regex:

'en koncert (pianist)'

Gruppen her er pianist omgivet af metakaraktererne (og). Det er faktisk en undergruppe, mens en koncert (pianist) er hele gruppen. Overvej følgende:

'(Pianisten er god)'

Her er undergruppen eller understrengen, pianist er god.

Understrenge med fælles dele

En bogholder er en person, der tager sig af bøger. Forestil dig et bibliotek med en bogholder og bogreol. Antag, at en af ​​følgende målstrenge er i computeren:

'Biblioteket har en reol, der beundres.';

'Her er bogholderen.';

'Bogføreren arbejder med reolen.';

Antag, at programmørens interesse ikke er at vide, hvilken af ​​disse sætninger der er i computeren. Alligevel er hans interesse at vide, om bogreol eller bogholder er til stede i den målstreng, der er i computeren. I dette tilfælde kan hans regex være:

'bogreol | bogholder.'

Brug af veksling.

Bemærk, at bogen, der er fælles for begge ord, er blevet skrevet to gange i de to ord i mønsteret. For at undgå at skrive bog to gange ville regex'en være bedre skrevet som:

'bog (hylde | beholder)'

Her er gruppen, hylde | keeper Alternativmetakarakteren har stadig været brugt, men ikke for to lange ord. Det er blevet brugt til de to slutdele af de to lange ord. C ++ behandler en gruppe som en enhed. Så C ++ vil lede efter en hylde eller beholder, der kommer umiddelbart efter bogen. Outputtet af følgende kode matches:

forkælelses[] = 'Biblioteket har en reol, der beundres.';

hvis (regex_search(s,regex('bog (hylde | beholder)')))

koste<< 'matchet' <<endl;

bogreol og ikke bogholder er blevet matchet.

Icase og multiline regex_constants

icase

Matchning er som standard følsom over for store og små bogstaver. Det kan dog gøres ufølsomt for sager. For at opnå dette skal du bruge regex :: icase -konstanten, som i følgende kode:

hvis (regex_search('Feedback',regex('foder',regex::icase)))

koste<< 'matchet' <<endl;

Outputtet matches. Så feedback med store 'F' er blevet matchet af feed med små 'f'. regex :: icase er blevet gjort til regex () -konstruktørens andet argument. Uden det ville udsagnet ikke producere et match.

Multiline

Overvej følgende kode:

forkælelses[] = 'linje 1 nlinje 2 nlinje 3 ';

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

koste<< 'matchet' <<endl;

andet

koste<< 'ikke matchet' <<endl;

Outputtet matcher ikke. Regexet, ^.*$, Matcher målstrengen fra begyndelsen til slutningen. .* betyder ethvert tegn undtagen n, nul eller flere gange. Så på grund af de nye linjetegn ( n) i målet var der ingen matchning.

Målet er en flerlinjes streng. For at '.' Kan matche newline -karakteren, skal den konstante regex :: multiline laves, det andet argument for regex () -konstruktionen. Følgende kode illustrerer dette:

forkælelses[] = 'linje 1 nlinje 2 nlinje 3 ';

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

koste<< 'matchet' <<endl;

andet

koste<< 'ikke matchet' <<endl;

Matcher hele målstrengen

For at matche hele målstrengen, som ikke har newline -tegnet ( n), kan funktionen regex_match () bruges. Denne funktion er forskellig fra regex_search (). Følgende kode illustrerer dette:

forkælelses[] = 'første anden tredje';

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

koste<< 'matchet' <<endl;

Der er en kamp her. Bemærk dog, at regex matcher hele målstrengen, og målstrengen ikke har nogen ‘ n’.

Match_results -objektet

Funktionen regex_search () kan tage et argument mellem målet og regex-objektet. Dette argument er match_results -objektet. Hele den matchede (del) streng og de matchede understrenge kan kendes med den. Dette objekt er et særligt array med metoder. Objekttypen match_results er cmatch (for strenglitteraler).

Indhentning af kampe

Overvej følgende kode:

forkælelses[] = 'Kvinden du ledte efter!';

cmatch m;

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

koste<<m[0] <<endl;

Målstrengen har ordet kvinde. Output er kvinde ’, hvilket svarer til regex, w.m.n. Ved indeks nul har den særlige matrix den eneste kamp, ​​som er kvinde.

Med klasseindstillinger sendes kun den første understreng, der findes i målet, til den specielle matrix. Følgende kode illustrerer dette:

cmatch m;

hvis (regex_search('Rotten, katten, flagermusen!',m,regex('[bcr] kl')))

koste<<m[0] <<endl;

koste<<m[1] <<endl;

koste<<m[2] <<endl;

Outputtet er rotte fra indeks nul. m [1] og m [2] er tomme.

Med alternativer sendes kun den første understreng, der findes i målet, til den specielle matrix. Følgende kode illustrerer dette:

hvis (regex_search('Kaninen, geden, grisen!',m,regex('ged | kanin | gris')))

koste<<m[0] <<endl;

koste<<m[1] <<endl;

koste<<m[2] <<endl;

Outputtet er kanin fra indeks nul. m [1] og m [2] er tomme.

Grupperinger

Når grupper er involveret, passer det komplette mønster ind i celle nul i det specielle array. Den næste understreng, der findes, går ind i celle 1; understrengen, der følger, går ind i celle 2; og så videre. Følgende kode illustrerer dette:

hvis (regex_search('Bedste boghandler i dag!',m,regex('bog ((sel) (ler))')))

koste<<m[0] <<endl;

koste<<m[1] <<endl;

koste<<m[2] <<endl;

koste<<m[3] <<endl;

Outputtet er:

boghandler

sælger

celle

Læs

Bemærk, at gruppen (sælger) kommer før gruppen (sel).

Matchens placering

Matchpositionen for hver understreng i cmatch-arrayet kan være kendt. Tællingen begynder fra det første tegn i målstrengen, i position nul. Følgende kode illustrerer dette:

cmatch m;

hvis (regex_search('Bedste boghandler i dag!',m,regex('bog ((sel) (ler))')))

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

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

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

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

Bemærk brugen af ​​egenskaben position, med celleindekset, som et argument. Outputtet er:

boghandler->5

sælger->9

celle->9

Læs->12

Søg og erstat

Et nyt ord eller en sætning kan erstatte kampen. Funktionen regex_replace () bruges til dette. Denne gang er strengen, hvor udskiftningen sker, imidlertid strengobjektet, ikke strengen bogstavelig. Så strengbiblioteket skal inkluderes i programmet. Illustration:

#omfatte

#omfatte

#omfatte

ved hjælp af navneområde std;

intvigtigste()
{
streng str= 'Her kommer min mand. Der går din mand. ';
streng newStr=regex_replace(s,regex('mand'), 'kvinde');
koste<<newStr<<endl;

Vend tilbage 0;
}

Funktionen regex_replace (), som kodet her, erstatter alle matchene. Funktionens første argument er målet, det andet er regex -objektet, og det tredje er erstatningsstrengen. Funktionen returnerer en ny streng, som er målet, men har erstatningen. Outputtet er:

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

Konklusion

Det regulære udtryk bruger mønstre til at matche substreringer i målsekvensstrengen. Mønstre har metategn. Almindeligt anvendte funktioner til C ++ regulære udtryk er: regex_search (), regex_match () og regex_replace (). Et regex er et mønster i dobbelte anførselstegn. Disse funktioner tager imidlertid regex -objektet som et argument og ikke kun regex. Regexet skal gøres til et regex -objekt, før disse funktioner kan bruge det.