C ++

Regular Expression Basics in C ++

Regular Expression Basics in C ++
Tänk på följande mening i citat:

"Här är min man."

Den här strängen kan finnas inne i datorn och användaren kanske vill veta om den har ordet "man". Om det har ordet man, kanske han vill ändra ordet "man" till "kvinna"; så att strängen ska läsa:

"Här är min kvinna."

Det finns många andra önskningar som dessa från datoranvändaren; vissa är komplexa. Regular Expression, förkortat, regex, är föremål för att hantera dessa problem via datorn. C ++ levereras med ett bibliotek som heter regex. Så bör ett C ++ - program för att hantera regex börja med:

#omfatta
#omfatta
använder namnrymd std;

Den här artikeln förklarar grunderna för reguljärt uttryck i C++.

Artikelinnehåll

  • Grundläggande uttryck för regelbundet uttryck
  • Mönster
  • Karaktärsklasser
  • Matchande vita utrymmen
  • Perioden (.) i mönstret
  • Matchande upprepningar
  • Matchande alternativ
  • Matchande början eller slut
  • Gruppering
  • Icas och multiline regex_constants
  • Matcha hela målet
  • Match_results-objektet
  • Matchens position
  • Sök och ersätt
  • Slutsats

Grundläggande uttryck för regelbundet uttryck

Regex

En sträng som ”Här är min man.”Ovan är målsekvensen eller målsträngen eller helt enkelt mål. ”Man”, som man sökte efter, är det vanliga uttrycket, eller helt enkelt, regex.

Motsvarande

Matchning sägs inträffa när ordet eller frasen som det söks efter finns. Efter matchning kan en ersättning äga rum. Till exempel, efter att "man" ligger ovanför kan den ersättas med "kvinna".

Enkel matchning

Följande program visar hur ordet ”man” matchas.

#omfatta
#omfatta
använder namnrymd std;
int main ()

regex reg ("man");
if (regex_search ("Här är min man.", reg))
cout << "matched" << endl;
annan
cout << "not matched" << endl;
returnera 0;

Funktionen regex_search () returnerar true om det finns en matchning och returnerar false om ingen matchning inträffar. Här tar funktionen två argument: det första är målsträngen och det andra är regex-objektet. Regexet i sig är "man", i dubbla citat. Det första uttalandet i huvudfunktionen () bildar regex-objektet. Regex är en typ och reg är regex-objektet. Ovanstående programs utdata är "matchade", eftersom "man" ses i målsträngen. Om "man" inte sågs i målet, skulle regex_search () ha returnerat falskt och utdata skulle "inte matchas".

Utgången från följande kod är "inte matchad":

regex reg ("man");
if (regex_search ("Här är min tillverkning.", reg))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

Inte matchad eftersom regex "man" inte kunde hittas i hela målsträngen, "Här är min tillverkning."

Mönster

Det reguljära uttrycket "man" ovan är väldigt enkelt. Regexes är vanligtvis inte så enkla. Regeluttryck har metatecken. Metatecken är tecken med speciella betydelser. En metatecken är en karaktär om karaktärer. C ++ regex-metatecken är:

^ $ \ . * + ? () [] |

En regex, med eller utan metatecken, är ett mönster.

Karaktärsklasser

Hakparentes

Ett mönster kan ha tecken inom hakparenteser. Med detta skulle en viss position i målsträngen matcha någon av hakparentesernas tecken. Tänk på följande mål:

"Katten är i rummet."
"Fladdermusen är i rummet."
"Råttan är i rummet."

Regex, [cbr] at skulle matcha katt i det första målet. Det skulle matcha bat i det andra målet. Det skulle matcha råtta i det tredje målet. Detta beror på att "katt" eller "fladdermus" eller "råtta" börjar med "c" eller "b" eller "r". Följande kodsegment illustrerar detta:

regex reg ("[cbr] at");
if (regex_search ("Katten är i rummet.", reg))
cout << "matched" << endl;
if (regex_search ("Fladdermusen är i rummet.", reg))
cout << "matched" << endl;
if (regex_search ("Råttan finns i rummet.", reg))
cout << "matched" << endl;

Utgången är:

matchade
matchade
matchade

Utbud av karaktärer

Klassen [cbr] i mönstret [cbr] skulle matcha flera möjliga tecken i målet. Det skulle matcha 'c' eller 'b' eller 'r' i målet. Om målet inte har något av "c", "b" eller "r", följt av "at", skulle det inte vara någon matchning.

Vissa möjligheter som 'c' eller 'b' eller 'r' finns inom ett intervall. Siffran 0 till 9 har 10 möjligheter och mönstret för det är [0-9]. Utbudet av små bokstäver, a till z, har 26 möjligheter, och mönstret för det är [a-z]. Utbudet av stora bokstäver, A till Z, har 26 möjligheter, och mönstret för det är [A-Z]. - är inte officiellt ett metakaraktär, men inom hakparenteser skulle det indikera ett intervall. Så, följande ger en matchning:

om (regex_search ("ID6id", regex ("[0-9]")))
cout << "matched" << endl;

Observera hur regex har konstruerats som det andra argumentet. Matchningen sker mellan siffran, 6 i intervallet, 0 till 9 och 6 i målet, "ID6id". Ovanstående kod motsvarar:

if (regex_search ("ID6id", regex ("[0123456789]")))
cout << "matched" << endl;

Följande kod ger en matchning:

char str [] = "ID6iE";
om (regex_search (str, regex ("[a-z]")))
cout << "matched" << endl;

Observera att det första argumentet här är en strängvariabel och inte strängens bokstav. Matchningen är mellan 'i' i [a-z] och 'i' i "ID6iE".

Glöm inte att ett intervall är en klass. Det kan finnas text till höger om intervallet eller till vänster om intervallet i mönstret. Följande kod ger en matchning:

om (regex_search ("ID2id är ett ID ", regex (" ID [0-9] id ")))
cout << "matched" << endl;

Matchningen är mellan “ID [0-9] id” och “ID2id”. Resten av målsträngen "är ett ID" matchas inte i denna situation.

Som används i ämnet för reguljära uttryck (regexes) betyder ordklassen faktiskt en uppsättning. Det vill säga att en av karaktärerna i uppsättningen ska matcha.

Obs! Bindestrecket - är en metatecken endast inom hakparenteser, vilket indikerar ett intervall. Det är inte en metakaraktär i regex, utanför hakparenteserna.

Negation

En klass med ett intervall kan negeras. Det vill säga att ingen av karaktärerna i uppsättningen (klass) ska matcha. Detta indikeras med ^ metatecken i början av klassmönstret, strax efter den inledande fyrkanten. Så, [^ 0-9] betyder att matcha tecknet i lämplig position i målet, vilket inte är något tecken i intervallet, inklusive 0 till 9. Så följande kod kommer inte att ge en matchning:

if (regex_search ("0123456789101112", regex ("[^ 0-9]")))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

En siffra inom intervallet 0 till 9 kan hittas i vilken som helst av målsträngpositionerna, "0123456789101112,"; så det finns ingen matchning - negation.

Följande kod ger en matchning:

om (regex_search ("ABCDEFGHIJ", regex ("[^ 0-9]")))
cout << "matched" << endl;

Ingen siffra kunde hittas i målet ”ABCDEFGHIJ”. så det finns en match.

[a-z] är ett område utanför [^ a-z]. Och så är [^ a-z] negationen av [a-z].

[A-Z] är ett område utanför [^ A-Z]. Och så är [^ A-Z] negationen av [A-Z].

Andra negationer finns.

Matchande vita utrymmen

"eller \ t eller \ r eller \ n eller \ f är ett mellanslagstecken. I följande kod matchar regex, “\ n” '\ n' i målet:

if (regex_search ("Av rad ett.\ r \ nRad två.", regex (" \ n ")))
cout << "matched" << endl;

Matchar valfritt tecken

Mönstret eller klassen som matchar alla vita blanksteg är, [\ t \ r \ n \ f]. I följande kod matchas ":

if (regex_search ("one two", regex ("[\ t \ r \ n \ f]")))
cout << "matched" << endl;

Matchar alla tecken som inte är blanksteg

Mönstret eller klassen som matchar alla tecken som inte är blanksteg är, [^ \ t \ r \ n \ f]. Följande kod skapar en matchning eftersom det inte finns något utrymme i målet:

om (regex_search ("1234abcd", regex ("[^ \ t \ r \ n \ f]")))
cout << "matched" << endl;

Perioden (.) i mönstret

Perioden (.) i mönstret matchar alla tecken inklusive sig själv, förutom \ n, i målet. En match produceras i följande kod:

om (regex_search ("1234abcd", regex (".")))
cout << "matched" << endl;

Inga matchande resultat i följande kod eftersom målet är “\ n”.

om (regex_search ("\ n", regex (".")))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

Obs! Inuti en karaktärsklass med hakparentes har perioden ingen speciell betydelse.

Matchande upprepningar

Ett tecken eller en grupp tecken kan förekomma mer än en gång i målsträngen. Ett mönster kan matcha denna upprepning. Metatecken, ?, *, + och används för att matcha repetitionen i målet. Om x är ett tecken av intresse i målsträngen har metatecken följande betydelser:

x *: betyder matchning 'x' 0 eller fler gånger, i.e., valfritt antal gånger
x +: betyder matchning 'x' 1 eller flera gånger, i.e., åtminstone en gång
x? : betyder matchning 'x' 0 eller 1 gång
x n,: betyder matchning 'x' minst n eller flera gånger. Notera komma.
x n: matcha 'x' exakt n gånger
x n, m: matcha 'x' minst n gånger, men inte mer än m gånger.

Dessa metatecken kallas kvantifierare.

Illustrationer

*

* Matchar föregående tecken eller föregående grupp, noll eller flera gånger. “O *” matchar "o" i "hund" i målsträngen. Det matchar också "oo" i "bok" och "ser". Regex, "o *" matchar "boooo" i "The animal booooed.”. Obs: “o *” matchar “dig”, där ”o” inträffar noll (eller mer) tid.

+

+ Matchar föregående tecken eller föregående grupp, 1 eller flera gånger. Kontrastera det med noll eller flera gånger för *. Så regex, "e +" matchar "e" i "äta", där "e" förekommer en gång. "E +" matchar också "ee" i "får", där "e" förekommer mer än en gång. Obs: “e +” matchar inte “dig” eftersom "e" inte förekommer minst en gång.

?

De ? matchar föregående tecken eller föregående grupp, 0 eller 1 gång (och inte mer). Så, "e?”Matchar“ gräva ”eftersom" e "förekommer i" gräv ", nolltid. “E?”Matchar“ set ”eftersom" e "förekommer i" set ", en gång. Obs: “e?”Matchar fortfarande” får ”; även om det finns två e i "får". Det finns en nyans här - se senare.

n,

Detta matchar minst n på varandra följande repetitioner av ett föregående tecken eller föregående grupp. Så regex, "e 2," matchar de två "e" i målet, "får", och de tre "e" i målet "sheeep". "E 2," matchar inte "set", eftersom "set" bara har en "e".

n

Detta matchar exakt n på varandra följande repetitioner av föregående tecken eller föregående grupp. Så regex, "e 2" matchar de två "e" i målet "får". "E 2" matchar inte "set" eftersom "set" bara har en "e". Tja, "e 2" matchar två 'e i målet, "sheeep". Det finns en nyans här - se senare.

n, m

Detta matchar flera upprepade repetitioner av ett föregående tecken eller föregående grupp, var som helst från n till m, inklusive. Så "e 1,3" matchar ingenting i "dig", som inte har något "e". Det matchar en 'e' i 'set', de två 'e i' får ', de tre' e 'i' sheeep 'och tre' e är i 'sheeeep'. Det finns en nyans vid den senaste matchen - se senare.

Matchande alternativ

Tänk på följande målsträng i datorn.

”Gården har grisar av olika storlek.”

Programmeraren kanske vill veta om det här målet har "get" eller "kanin" eller "gris". Koden skulle vara som följer:

char str [] = "Gården har svin i olika storlekar.";
om (regex_search (str, regex ("get | kanin | gris")))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

Koden skapar en matchning. Observera användningen av alterneringstecknet |. Det kan finnas två, tre, fyra och fler alternativ. C ++ försöker först matcha det första alternativet "get" vid varje teckenposition i målsträngen. Om det inte lyckas med "get", försöker det nästa alternativ, "kanin". Om det inte lyckas med "kanin" försöker det nästa alternativ, "gris". Om “gris” misslyckas går C ++ vidare till nästa position i målet och börjar med det första alternativet igen.

I ovanstående kod matchas ”gris”.

Matchande början eller slut

Början


Om ^ är i början av regex, kan målsträngens starttext matchas av regex. I följande kod är målets start "abc", vilket matchas:

om (regex_search ("abc och def", regex ("^ abc")))
cout << "matched" << endl;

Ingen matchning sker i följande kod:

om (regex_search ("Ja, abc och def", regex ("^ abc")))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

Här är "abc" inte i början av målet.

Obs! Omfångstecken, '^', är en metatecken i början av regex, som matchar början av målsträngen. Det är fortfarande en metakaraktär i början av karaktärsklassen, där den negerar klassen.

Slutet

Om $ är i slutet av regex kan målsträngens sluttext matchas av regex. I följande kod är slutet på målet “xyz”, vilket matchas:

om (regex_search ("uvw och xyz", regex ("xyz $")))
cout << "matched" << endl;

Ingen matchning sker i följande kod:

om (regex_search ("uvw och xyz final", regex ("xyz $")))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

Här är “xyz” inte i slutet av målet.

Gruppering

Parenteser kan användas för att gruppera tecken i ett mönster. Tänk på följande regex:

"en konsert (pianist)"

Gruppen här är "pianist" omgiven av metatecken (och). Det är faktiskt en undergrupp, medan "en konsert (pianist)" är hela gruppen. Tänk på följande:

"(Pianisten är bra)"

Här är undergruppen eller understrängen "pianist är bra".

Understrängar med gemensamma delar

En bokhållare är en person som tar hand om böcker. Föreställ dig ett bibliotek med en bokhållare och en bokhylla. Antag att en av följande målsträngar finns i datorn:

"Biblioteket har en bokhylla som beundras.";
"Här är bokhållaren.";
"Bokhållaren arbetar med bokhyllan.";

Antag att programmerarens intresse inte är att veta vilken av dessa meningar som finns i datorn. Ändå är hans intresse att veta om "bokhylla" eller "bokhållare" finns i vilken målsträng som helst i datorn. I det här fallet kan hans regex vara:

"bokhylla | bokhållare."

Använda alternering.

Lägg märke till att ”boken”, som är gemensam för båda orden, har skrivits två gånger, i de två orden i mönstret. För att undvika att skriva "bok" två gånger skulle regex bättre skrivas som:

"bok (hylla | djurhållare)"

Här har gruppen "hylla | djurhållare" Alternativmetatecknet fortfarande använts, men inte för två långa ord. Det har använts för de två slutdelarna av de två långa orden. C ++ behandlar en grupp som en enhet. Så C ++ kommer att leta efter "hylla" eller "djurhållare" som kommer direkt efter "bok". Utgången från följande kod är "matchad":

char str [] = "Biblioteket har en bokhylla som beundras.";
if (regex_search (str, regex ("book (shelf | keeper)")))
cout << "matched" << endl;

"Bokhylla" och inte "bokhållare" har matchats.

Icas och multiline regex_constants

icase

Matchning är skiftlägeskänslig som standard. Det kan dock göras skiftlägeskänsligt. För att uppnå detta använder du regex :: icase-konstanten, som i följande kod:

if (regex_search ("Feedback", regex ("feed", regex :: icase)))
cout << "matched" << endl;

Utgången är "matchad". Så "Feedback" med stora bokstäver "F" har matchats av "feed" med gemener "f". “Regex :: icase” har gjorts till det andra argumentet för regex () -konstruktören. Utan det skulle uttalandet inte skapa en matchning.

Multilinje

Tänk på följande kod:

char str [] = "rad 1 \ nline 2 \ nline 3";
om (regex_search (str, regex ("^.* $ ")))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

Utgången är "inte matchad". Regex, “^.* $, ”Matchar målsträngen från början till slutet. “.* ”Betyder alla tecken utom \ n, noll eller fler gånger. Så på grund av de nya linjetecknen (\ n) i målet fanns det ingen matchning.

Målet är en sträng med flera linjer. För att '.'för att matcha den nya linjetecknet måste den konstanta "regex :: multiline" göras, det andra argumentet för regex () -konstruktionen. Följande kod illustrerar detta:

char str [] = "rad 1 \ nline 2 \ nline 3";
om (regex_search (str, regex ("^.* $ ", regex :: multiline)))
cout << "matched" << endl;
annan
cout << "not matched" << endl;

Matcha hela målsträngen

För att matcha hela målsträngen, som inte har den nya linjetecknet (\ n), kan funktionen regex_match () användas. Denna funktion skiljer sig från regex_search (). Följande kod illustrerar detta:

char str [] = "första andra tredjedelen";
om (regex_match (str, regex (".*andra.* ")))
cout << "matched" << endl;

Det finns en match här. Observera dock att regex matchar hela målsträngen och att målsträngen inte har någon '\ n'.

Match_results-objektet

Funktionen regex_search () kan ta ett argument mellan målet och regex-objektet. Detta argument är match_results-objektet. Hela matchade (del) sträng och understrängar som matchas kan kännas med den. Detta objekt är en speciell matris med metoder. Objekttypen match_results är cmatch (för stränglitterärer).

Få matchningar

Tänk på följande kod:

char str [] = "Kvinnan du letade efter!";
cmatch m;
om (regex_search (str, m, regex ("w.m.n ")))
cout << m[0] << endl;

Målsträngen har ordet ”kvinna”. Produktionen är "kvinna", vilket motsvarar regex, "w.m.n ”. Vid index noll innehåller specialmatrisen den enda matchningen, som är "kvinna".

Med klassalternativ skickas endast den första understrängen som hittas i målet till specialmatrisen. Följande kod illustrerar detta:

cmatch m;
if (regex_search ("Råttan, katten, fladdermusen!", m, regex (" [bcr] at ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

Produktionen är "rat" från index noll. m [1] och m [2] är tomma.

Med alternativ skickas bara den första understrängen som hittas i målet till specialmatrisen. Följande kod illustrerar detta:

if (regex_search ("Kaninen, geten, grisen!", m, regex (" get | kanin | gris ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

Utgången är ”kanin” från index noll. m [1] och m [2] är tomma.

Grupperingar

När grupper är inblandade, matchas hela mönstret till cell noll i specialmatrisen. Nästa understräng som hittas går in i cell 1; delsträngen som följer, går in i cell 2; och så vidare. Följande kod illustrerar detta:

if (regex_search ("Bästa bokförsäljare idag!", m, regex (" book ((sel) (ler)) "))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;

Utgången är:

bokhandlare
säljare
sel
ler

Observera att gruppen (säljaren) kommer före gruppen (sel).

Matchens position

Matchningspositionen för varje delsträng i cmatch-matrisen kan vara känd. Räkningen börjar från målsträngens första tecken, vid position noll. Följande kod illustrerar detta:

cmatch m;
if (regex_search ("Bästa bokförsäljare idag!", m, regex (" book ((sel) (ler)) "))
cout << m[0] << "->" << m.position(0) << endl;
cout << m[1] << "->" << m.position(1) << endl;
cout << m[2] << "->" << m.position(2) << endl;
cout << m[3] << "->" << m.position(3) << endl;

Notera användningen av positionsegenskapen med cellindex som ett argument. Utgången är:

bokhandlare-> 5
säljare-> 9
sel-> 9
ler-> 12

Sök och ersätt

Ett nytt ord eller en ny fras kan ersätta matchningen. Funktionen regex_replace () används för detta. Men den här gången är strängen där ersättningen sker strängobjektet, inte strängen bokstavligt. Så strängbiblioteket måste ingå i programmet. Illustration:

#omfatta
#omfatta
#omfatta
använder namnrymd std;
int main ()

string str = "Här kommer min man. Där går din man.";
sträng newStr = regex_replace (str, regex ("man"), "kvinna");
cout << newStr << endl;
returnera 0;

Funktionen regex_replace (), som kodad här, ersätter alla matchningar. Funktionens första argument är målet, det andra är regex-objektet och det tredje är ersättningssträngen. Funktionen returnerar en ny sträng, som är målet men som har ersättningen. Utgången är:

”Här kommer min kvinna. Där går din kvinna.”

Slutsats

Det reguljära uttrycket använder mönster för att matcha strängar i målsekvenssträngen. Mönster har metatecken. Vanligt använda funktioner för C ++ reguljära uttryck är: regex_search (), regex_match () och regex_replace (). En regex är ett mönster i dubbla citat. Dessa funktioner tar dock regex-objektet som ett argument och inte bara regex. Regex måste göras till ett regex-objekt innan dessa funktioner kan använda det.

Mus Hur man ändrar vänster och höger musknapp på Windows 10 PC
Hur man ändrar vänster och höger musknapp på Windows 10 PC
Det är en hel norm att alla datormusenheter är ergonomiskt utformade för högerhänta användare. Men det finns musenheter tillgängliga som är speciellt ...
Mus Emulera musklick genom att sväva med Clickless Mouse i Windows 10
Emulera musklick genom att sväva med Clickless Mouse i Windows 10
Att använda en mus eller tangentbord i fel hållning av överdriven användning kan resultera i många hälsoproblem, inklusive stam, karpaltunnelsyndrom o...
Mus Lägg till musgester i Windows 10 med dessa gratisverktyg
Lägg till musgester i Windows 10 med dessa gratisverktyg
Under senare år har datorer och operativsystem utvecklats kraftigt. Det fanns en tid då användare var tvungna att använda kommandon för att navigera g...