C ++

Osnove redovitog izražavanja na C ++

Osnove redovitog izražavanja na C ++
Sljedeću rečenicu uzmite u navodnike:

"Evo mog čovjeka."

Ovaj se niz možda nalazi u računalu i korisnik bi možda želio znati ima li riječ "čovjek". Ako ima riječ muškarac, on bi tada mogao promijeniti riječ "muškarac" u "žena"; tako da niz treba glasiti:

"Evo moje žene."

Postoje mnoge druge želje poput ovih od korisnika računala; neki su složeni. Regularni izraz, skraćeno, regularni izraz, predmet je rješavanja ovih problema putem računala. C ++ dolazi s bibliotekom zvanom regex. Dakle, C ++ program za rukovanje regularnim izrazom trebao bi započeti sa:

#include
#include
pomoću prostora imena std;

Ovaj članak objašnjava osnove redovitog izražavanja u jeziku C++.

Sadržaj članka

  • Osnove redovnog izražavanja
  • Uzorak
  • Razredi likova
  • Odgovarajući razmaci
  • Menstruacija (.) u Obrascu
  • Podudaranje ponavljanja
  • Odgovarajuća izmjena
  • Podudaranje početka ili kraja
  • Grupiranje
  • Icase i višeredne_regex_constants
  • Podudaranje s cijelom metom
  • Predmet match_results
  • Položaj utakmice
  • Traži i zamijeni
  • Zaključak

Osnove redovnog izražavanja

Regex

Niz poput „Evo mog čovjeka.”Gore je ciljni slijed ili ciljni niz ili jednostavno cilj. "Čovjek", za kojim se tragalo, regularni je izraz, ili jednostavno, regex.

Podudaranje

Kaže se da se podudaranje događa kada se pronađe riječ ili izraz koji se traži. Nakon podudaranja može se dogoditi zamjena. Na primjer, nakon što se iznad nalazi "muškarac", može ga zamijeniti "žena".

Jednostavno podudaranje

Sljedeći program pokazuje kako se podudara riječ "čovjek".

#include
#include
pomoću prostora imena std;
int main ()

regularni izraz reg ("čovjek");
if (regex_search ("Evo mog čovjeka.", reg))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;
return 0;

Funkcija regex_search () vraća true ako postoji podudaranje i vraća false ako se ne podudara. Ovdje funkcija uzima dva argumenta: prvi je ciljni niz, a drugi je objekt regularnog izraza. Sam regularni izraz je "čovjek", u dvostrukim navodnicima. Prva izjava u funkciji main () tvori objekt regularnog izraza. Redovni izraz je vrsta, a reg je objekt regularnog izraza. Izlaz gornjeg programa se "podudara", kao što se u ciljnom nizu vidi "čovjek". Da se "target" nije vidio u cilju, regex_search () bi vratio false, a izlaz bi bio "ne odgovara".

Izlaz sljedećeg koda se „ne podudara“:

regex reg ("čovjek");
if (regex_search ("Evo moje izrade.", reg))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Nije podudarno jer regularni izraz "man" nije mogao biti pronađen u cijelom ciljnom nizu, "Evo moje izrade."

Uzorak

Regularni izraz, "čovjek" gore, vrlo je jednostavan. Regeksi obično nisu tako jednostavni. Regularni izrazi imaju metaznakove. Metaznakovi su likovi s posebnim značenjima. Metaznak je lik o likovima. Metaznakovi C ++ regularnog izraza su:

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

Redovni izraz, sa ili bez metaznaka, obrazac je.

Razredi likova

Uglate zagrade

Uzorak može imati znakove unutar uglatih zagrada. S tim bi se određena pozicija u ciljnom nizu podudarala s bilo kojim od uglastih zagrada. Razmotrite sljedeće ciljeve:

"Mačka je u sobi."
"Šišmiš je u sobi."
"Štakor je u sobi."

Redovni izraz, [cbr] at odgovarao bi mački u prvom cilju. Podudarao bi se s palicom u drugoj meti. Odgovarao bi pacovu u trećoj meti. To je zato što "mačka" ili "šišmiš" ili "štakor" počinje s "c" ili "b" ili "r". Sljedeći segment koda to ilustrira:

regularni izraz reg ("[cbr] at");
if (regex_search ("Mačka je u sobi.", reg))
cout << "matched" << endl;
if (regex_search ("Šišmiš je u sobi.", reg))
cout << "matched" << endl;
if (regex_search ("Štakor je u sobi.", reg))
cout << "matched" << endl;

Izlaz je:

podudarne
podudarne
podudarne

Raspon likova

Klasa, [cbr] u uzorku [cbr], podudarala bi se s nekoliko mogućih znakova u cilju. U cilju bi se podudarao s 'c' ili 'b' ili 'r'. Ako cilj nema bilo koji od 'c' ili 'b' ili 'r', nakon čega slijedi "at", ne bi bilo podudaranja.

Neke mogućnosti poput 'c' ili 'b' ili 'r' postoje u rasponu. Raspon znamenki, od 0 do 9, ima 10 mogućnosti, a obrazac za to je [0-9]. Raspon malih abeceda, od a do z, ima 26 mogućnosti, a obrazac za to je [a-z]. Raspon velikih abeceda, od A do Ž, ima 26 mogućnosti, a obrazac za to je [A-Z]. - nije službeno metaznak, ali unutar uglatih zagrada označavao bi raspon. Dakle, sljedeće daje podudaranje:

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

Primijetite kako je regex konstruiran kao drugi argument. Podudaranje se događa između znamenke, 6 u rasponu, od 0 do 9, i 6 u cilju, "ID6id". Gornji kod je ekvivalentan:

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

Sljedeći kod daje podudaranje:

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

Imajte na umu da je prvi argument ovdje varijabla niza, a ne literal niza. Podudaranje je između 'i' u [a-z] i 'i' u "ID6iE".

Ne zaboravite da je raspon klasa. Na uzorku može biti tekst s desne strane raspona ili s lijeve strane raspona. Sljedeći kod daje podudaranje:

if (regex_search ("ID2id je ID ", regularni izraz (" ID [0-9] id ")))
cout << "matched" << endl;

Podudaranje je između "ID [0-9] id" i "ID2id". Ostatak ciljnog niza, "je ID", u ovoj se situaciji ne podudara.

Kako se koristi u subjektu regularnog izraza (regularni izrazi), riječ class zapravo znači skup. Odnosno, jedan od likova u setu mora se podudarati.

Napomena: crtica - je metaznak samo unutar uglatih zagrada, koji označava raspon. To nije metaznak u regularnom izrazu, izvan kvadratnih zagrada.

Negacija

Klasa koja uključuje raspon može se negirati. Odnosno, nijedan od znakova u skupu (klasi) ne bi se trebao podudarati. To je naznačeno znakom ^ na početku uzorka klase, odmah nakon početne uglate zagrade. Dakle, [^ 0-9] znači podudaranje znaka na odgovarajućem položaju u cilju, što nije nijedan znak u rasponu, uključujući 0 do 9. Dakle, sljedeći kod neće stvoriti podudaranje:

if (traženje_regeksa ("0123456789101112", regex ("[^ 0-9]")))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Znamenka u rasponu od 0 do 9 može se naći u bilo kojem od ciljnih položaja niza, "0123456789101112"; tako da nema podudaranja - negacije.

Sljedeći kod daje podudaranje:

if (pretraga_regeksa ("ABCDEFGHIJ", regularni izraz ("[^ 0-9]")))
cout << "matched" << endl;

U cilju, "ABCDEFGHIJ", nije se mogla pronaći nijedna znamenka; pa postoji šibica.

[a-z] je raspon izvan [^ a-z]. I tako je [^ a-z] negacija [a-z].

[A-Z] je raspon izvan [^ A-Z]. I tako je [^ A-Z] negacija [A-Z].

Postoje i druge negacije.

Odgovarajući razmaci

"ili \ t ili \ r ili \ n ili \ f je razmak. U sljedećem kodu, regularni izraz, "\ n" se podudara s "\ n" u cilju:

if (regex_search ("Reda jedan.\ r \ nDrugog retka.", regularni izraz (" \ n ")))
cout << "matched" << endl;

Podudaranje s bilo kojim praznim znakom

Uzorak ili klasa koja odgovara bilo kojem razmaku znaka je, [\ t \ r \ n \ f]. U sljedećem kodu podudara se: "

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

Podudaranje s bilo kojim znakom koji nije razmak

Uzorak ili klasa koja odgovara bilo kojem znaku koji nije prazan je: [^ \ t \ r \ n \ f]. Sljedeći kôd daje podudaranje jer nema razmaka u cilju:

if (traženje_regeksa ("1234abcd", regex ("[^ \ t \ r \ n \ f]")))
cout << "matched" << endl;

Menstruacija (.) u Obrascu

Menstruacija (.) u uzorku odgovara bilo kojem liku, uključujući sebe, osim \ n, u cilju. Podudaranje se proizvodi u sljedećem kodu:

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

U sljedećem kodu nema podudarnih rezultata jer je cilj "\ n".

if (regex_search ("\ n", regularni izraz (".")))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Napomena: Unutar klase znakova s ​​uglastim zagradama točka nema posebno značenje.

Podudaranje ponavljanja

Znak ili grupa znakova mogu se pojaviti više puta u ciljnom nizu. Uzorak može odgovarati ovom ponavljanju. Metaznakovi, ?, *, + i se koriste za podudaranje ponavljanja u cilju. Ako je x karakter od interesa u ciljnom nizu, tada metaznakovi imaju sljedeća značenja:

x *: znači podudaranje 'x' 0 ili više puta, tj.e., bilo koji broj puta
x +: znači podudaranje 'x' 1 ili više puta, tj.e., barem jednom
x? : znači podudaranje 'x' 0 ili 1 put
x n,: znači podudaranje 'x' najmanje n ili više puta. Obratite pažnju na zarez.
x n: podudaranje s 'x' točno n puta
x n, m: podudaranje s 'x' najmanje n puta, ali ne više od m puta.

Ti se metakarakteri nazivaju kvantifikatorima.

Ilustracije

*

Znak * odgovara prethodnom znaku ili prethodnoj grupi, nula ili više puta. "O *" se podudara s "o" u "dog" ciljnog niza. Također se podudara s "oo" u "book" i "looking". Redovni izraz "o *" podudara se s "boooo" u "Životinja je booooed".". Napomena: "o *" se podudara s "dig", gdje se "o" javlja nula (ili više) vremena.

+

Znak + odgovara prethodnom znaku ili prethodnoj grupi 1 ili više puta. Usporedite ga s nula ili više puta za *. Dakle, regularni izraz "e +" podudara se s "e" u "jesti", gdje se "e" javlja jednom. "E +" se također podudara s "ee" u "ovaca", gdje se "e" pojavljuje više puta. Napomena: "e +" se neće podudarati s "dig" jer se u "dig" "e" ne pojavljuje barem jednom.

?

The ? odgovara prethodnom znaku ili prethodnoj grupi, 0 ili 1 puta (i ne više). Dakle, „npr?”Podudara se s„ dig ”, jer se„ e ”pojavljuje u„ dig ”, nula vremena. „E?”Podudara se s„ set ”, jer se„ e ”javlja u„ skupu ”, jednokratno. Napomena: „e?”I dalje se podudara s„ ovcama ”; iako postoje dva e u "ovce". Ovdje postoji nijansa - pogledajte kasnije.

n,

Ovo se podudara s najmanje n uzastopnih ponavljanja prethodnog znaka ili prethodne grupe. Dakle, regularni izraz, "e 2,", podudara se s dva e u cilju, "ovca", i tri e u cilju "ovca". "E 2," se ne podudara s "set", jer "set" ima samo jedno "e".

n

To se podudara s točno n uzastopnih ponavljanja prethodnog znaka ili prethodne grupe. Dakle, regularni izraz "e 2" podudara se s dva e u cilju, "ovca". "E 2" se ne podudara s "set", jer "set" ima samo jedno "e". Pa, "e 2" se podudara s dva e u cilju, "ovca". Ovdje postoji nijansa - pogledajte kasnije.

n, m

Ovo se podudara s nekoliko uzastopnih ponavljanja prethodnog znaka ili prethodne skupine, bilo gdje od n do m, uključujući. Dakle, "e 1,3" se ne podudara ni sa čim u "dig", koji nema "e". Odgovara onom 'e' u "setu", dva e u "ovca", tri e u "ovca" i tri e u "sheeeep". Na posljednjem meču postoji nijansa - pogledajte kasnije.

Odgovarajuća izmjena

Razmotrite sljedeći ciljni niz u računalu.

“Na farmi se nalaze svinje različitih veličina."

Programer bi mogao znati ima li ovaj cilj "kozu", "zeca" ili "svinju". Kôd bi bio sljedeći:

char str [] = "Farma ima svinje različitih veličina.";
if (regex_search (str, regex ("koza | zec | svinja")))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Kod daje podudaranje. Obratite pažnju na upotrebu znaka izmjene, |. Mogu biti dvije, tri, četiri i više opcija. C ++ će prvo pokušati podudarati se s prvom alternativom, "jarcem", na svakom položaju znaka u ciljnom nizu. Ako ne uspije s "jarcem", pokušava sljedeću alternativu, "zec". Ako ne uspije s "zecom", pokušava sljedeću alternativu, "svinja". Ako “pig” zakaže, tada C ++ prelazi na sljedeće mjesto u cilju i ponovno započinje s prvom alternativom.

U gornjem kodu podudara se "svinja".

Podudaranje početka ili kraja

Početak


Ako je ^ na početku regularnog izraza, tada se regularni izraz može podudarati s početkom teksta ciljnog niza. U sljedećem kodu početak cilja je "abc", koji se podudara:

if (regex_search ("abc and def", regex ("^ abc")))
cout << "matched" << endl;

U sljedećem se kodu ne podudara:

if (regex_search ("Da, abc i def", regex ("^ abc")))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Ovdje "abc" nije na početku cilja.

Napomena: Znak cirkumfleksa, '^', metaznak je na početku regularnog izraza, koji odgovara početku ciljnog niza. To je još uvijek metaznak na početku klase znakova, gdje negira klasu.

Kraj

Ako je $ na kraju regularnog izraza, tada se regularni izraz može podudarati sa završnim tekstom ciljnog niza. U sljedećem kodu kraj cilja je "xyz", koji se podudara:

if (regex_search ("uvw i xyz", regex ("xyz $")))
cout << "matched" << endl;

U sljedećem se kodu ne podudara:

if (regex_search ("uvw i xyz final", regex ("xyz $")))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Ovdje "xyz" nije na kraju cilja.

Grupiranje

Zagrade se mogu koristiti za grupiranje znakova u obrazac. Razmotrite sljedeći regularni izraz:

"koncert (pijanist)"

Ovdje je skupina "pijanistica" okružena metaznacima (i). To je zapravo podskupina, dok je “koncert (pijanist)” cijela grupa. Uzmite u obzir sljedeće:

"The (pijanist je dobar)"

Ovdje je podskupina ili podskupina "pijanist dobar".

Podnizovi sa zajedničkim dijelovima

Knjigovođa je osoba koja se brine o knjigama. Zamislite knjižnicu s knjigovođom i policom. Pretpostavimo da je jedan od sljedećih ciljnih nizova u računalu:

"Knjižnica ima policu s knjigama kojoj se dive.";
"Evo knjigovođe.";
"Knjigovođa radi s policom za knjige.";

Pretpostavimo da programer ne želi znati koja se od ovih rečenica nalazi u računalu. Ipak, njegov je interes znati je li "polica za knjige" ili "knjigovođa" prisutna u bilo kojem ciljanom nizu u računalu. U ovom slučaju, njegov regularni izraz može biti:

"polica za knjige | knjigovođa."

Koristeći alternaciju.

Primijetite da je "knjiga", koja je zajednička objema riječima, upisana dva puta, u dvije riječi u uzorku. Da biste izbjegli da dvaput upišete "book", regularni izraz bi bilo bolje napisati kao:

"knjiga (polica | čuvar)"

Ovdje je grupa, "polica | čuvar" Metaznak izmjene i dalje se koristi, ali ne za dvije duge riječi. Upotrijebljen je za dva završna dijela dviju dugih riječi. C ++ grupu tretira kao entitet. Dakle, C ++ će tražiti "policu" ili "čuvara" koji dolazi odmah nakon "knjige". Izlaz sljedećeg koda se "podudara":

char str [] = "Biblioteka ima policu s knjigama kojoj se dive.";
if (regex_search (str, regex ("knjiga (polica | čuvar)")))
cout << "matched" << endl;

"Polica za knjige", a ne "knjigovođa", podudaraju se.

Icase i višeredne_regex_constants

icase

Podudaranje prema zadanim postavkama razlikuje velika i mala slova. Međutim, može se učiniti neosjetljivim na velika i mala slova. Da biste to postigli, upotrijebite konstantu regex :: icase, kao u sljedećem kodu:

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

Izlaz se "podudara". Dakle, „Povratne informacije“ s velikim slovom „F“ podudaraju se s „unosima“ s malim slovom „f“. “Regex :: icase” je drugi argument konstruktora regex (). Bez toga izjava ne bi dala podudarnost.

Multiline

Razmotrite sljedeći kod:

char str [] = "redak 1 \ n redak 2 \ n redak 3";
if (regex_search (str, regex ("^.* $ ")))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Izlaz se "ne podudara". Redovni izraz, "^.* $, ”Podudara se s ciljnim nizom od početka do kraja. “.* ”Znači bilo koji znak, osim \ n, nula ili više puta. Dakle, zbog znakova novog retka (\ n) u cilju, nije bilo podudaranja.

Cilj je višeredni niz. Da bi.'kako bi se podudarao sa znakom nove linije, mora se napraviti konstanta "regex :: multiline", drugi argument konstrukcije regex (). Sljedeći kod to ilustrira:

char str [] = "redak 1 \ n redak 2 \ n redak 3";
if (regex_search (str, regex ("^.* $ ", regularni izraz :: višeredni))))
cout << "matched" << endl;
drugo
cout << "not matched" << endl;

Podudaranje cijelog ciljanog niza

Da bi se podudarao s cijelim ciljnim nizom, koji nema znak novog retka (\ n), može se koristiti funkcija regex_match (). Ova se funkcija razlikuje od regex_search (). Sljedeći kod to ilustrira:

char str [] = "prva druga trećina";
if (regex_match (str, regex (".*drugi.* ")))
cout << "matched" << endl;

Ovdje se podudara. Međutim, imajte na umu da se regularni izraz podudara s cijelim ciljnim nizom, a ciljni niz nema '\ n'.

Predmet match_results

Funkcija regex_search () može uzeti argument između cilja i objekta regularnog izraza. Ovaj argument je objekt match_results. Čitav podudarani (dio) niz i pod-nizovi koji se podudaraju mogu se znati s njim. Ovaj je objekt poseban niz s metodama. Tip objekta match_results je cmatch (za string literale).

Dobivanje utakmica

Razmotrite sljedeći kod:

char str [] = "Žena koju ste tražili!";
meč m;
if (regex_search (str, m, regex ("w.m.n ")))
cout << m[0] << endl;

Ciljni niz ima riječ "žena". Rezultat je "žena", što odgovara regularnom izrazu, "w.m.n ”. Na indeksu nula, poseban niz sadrži jedino podudaranje, a to je "žena".

S opcijama klase, samo se prvi podniz koji se nalazi u cilju šalje u poseban niz. Sljedeći kod to ilustrira:

meč m;
if (regex_search ("Štakor, mačka, šišmiš!", m, regularni izraz (" [bcr] at ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

Izlaz je "rat" iz indeksa nula. m [1] i m [2] su prazni.

S alternativama, samo se prva podniza pronađena u cilju šalje u posebnu matricu. Sljedeći kod to ilustrira:

if (regex_search ("zec, jarac, svinja!", m, regex (" koza | zec | svinja ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

Izlaz je "zec" iz indeksa nula. m [1] i m [2] su prazni.

Grupiranja

Kada su uključene grupe, kompletan obrazac koji se podudara ide u nulu ćelije posebnog niza. Sljedeći pronađeni podniz ulazi u ćeliju 1; podniz koji slijedi, ide u ćeliju 2; i tako dalje. Sljedeći kod to ilustrira:

if (regex_search ("Najbolji prodavač knjiga danas!", m, regex (" book ((sel) (ler)) ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;

Izlaz je:

knjižar
prodavač
sel
ler

Imajte na umu da grupa (prodavač) dolazi prije grupe (sel).

Položaj utakmice

Položaj podudaranja za svaki podniz u polju cmatch može biti poznat. Brojanje započinje od prvog znaka ciljnog niza, na položaju nula. Sljedeći kod to ilustrira:

meč m;
if (regex_search ("Najbolji prodavač knjiga danas!", 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;

Primijetite upotrebu svojstva position s indeksom ćelije kao argument. Izlaz je:

prodavač knjiga-> 5
prodavač-> 9
sel-> 9
ler-> 12

Traži i zamijeni

Nova riječ ili fraza mogu zamijeniti podudaranje. Za to se koristi funkcija regex_replace (). Međutim, ovaj put je niz u kojem dolazi do zamjene objekt niza, a ne literal niza. Dakle, knjižnica stringova mora biti uključena u program. Ilustracija:

#include
#include
#include
pomoću prostora imena std;
int main ()

string str = "Evo, dolazi moj čovjek. Ode tvoj čovjek.";
string newStr = regex_replace (str, regex ("muškarac"), "žena");
cout << newStr << endl;
return 0;

Funkcija regex_replace (), kako je ovdje kodirana, zamjenjuje sva podudaranja. Prvi argument funkcije je cilj, drugi je objekt regularnog izraza, a treći je zamjenski niz. Funkcija vraća novi niz, koji je cilj, ali koji ima zamjenu. Izlaz je:

“Evo moje žene. Ode tvoja žena."

Zaključak

Regularni izraz koristi uzorke za podudaranje podnizova u nizu ciljane sekvence. Obrasci imaju metaznakove. Uobičajene funkcije za regularne izraze C ++ su: regex_search (), regex_match () i regex_replace (). Redovni izraz je obrazac u dvostrukim navodnicima. Međutim, ove funkcije kao argument uzimaju objekt regularnog izraza, a ne samo regularni izraz. Redovni izraz mora se pretvoriti u objekt regularnog izraza da bi ga ove funkcije mogle koristiti.

Emulirajte klikove mišem lebdeći mišem bez klika u sustavu Windows 10
Korištenje miša ili tipkovnice u pogrešnom držanju pretjerane upotrebe može rezultirati mnogim zdravstvenim problemima, uključujući naprezanje, sindro...
Dodajte geste miša u sustav Windows 10 pomoću ovih besplatnih alata
Posljednjih godina računala i operativni sustavi uvelike su se razvili. Bilo je vrijeme kada su korisnici morali koristiti naredbe za navigaciju kroz ...
Kontrolirajte i upravljajte kretanjem miša između više monitora u sustavu Windows 10
Dvostruki zaslon upravitelja miša omogućuje vam kontrolu i konfiguriranje kretanja miša između više monitora, usporavajući njegovo kretanje blizu gran...