Az itteni regex motor is támogatja többek közt ezeket a műveleteket:
illeszkedik-e egy teljes input szöveg egy regexre (match bool), a std::regex_match függvénnyel
illeszkedés esetén capturing groupok tartalmának kigyűjtésére (match groups), a regex_matchnek megadva egy std::smatch objektumot
is, melybe az illeszkedés részletei kerülnek, pl. a csoportok;
input szövegben az input regexre első illeszkedő substring megkereresése (search), a std::regex_search függvénnyel
input szövegben az input regexre illeszkedő substringek, vagy közülük csak az első cseréje valamire (replaceAll, replace),
a std::regex_replace függvénnyel
Lássunk egy egyszerű "illik-e vagy sem" kódot: megkeressük (ggmarkk után szabadon), hogy az input
stringünkben vajon szerepel-e (külön szóként) a "telefon" szó.
1 2 3 4 5 6 7 8 9101112131415161718192021
#include<regex> // std::regex osztály, std::regex_match függvény, C++11 óta része#include<string> // std::string#include<iostream> // std::cout, std::endl// using namespace std; // ízlés dolga, hogy ki szereti behúzni az egész névteret// using std::string; // vagy csak egy-egy osztályt belőle// vagy kiírja mindig, hogy std::string, string helyett...// arra a stringekre illik, melyek tartalmazzák a "telefon" szótstd::regextheRegex(".*\\btelefon\\b.*");// c++ alapból használjunk std::stringet, ha lehet std::stringtheText="alma körte telefon barack";if(std::regex_match(// regex_match: bool, illik-etheText,// erre a std::string vagy char* szövegre theRegex))// ez a std::regex{std::cout<<"a regex illik a szövegre"<<std::endl;}else{std::cout<<"a regex NEM illik a szövegre"<<std::endl;}
Ha az illesztést úgy szeretnénk elvégezni, hogy utána a capturing groupokkal is szeretnénk kezdeni valamit,
adnunk kell egy std::regex_match referenciát a regex_matchnek, második argumentumként.
Ez egy template osztály, ugyanazzal a karaktertípussal kell példányosítsuk, mint ami az input text stringnek
a karaktertípusa -- de két példányosztály aliasolva van nekünk előre: ha char * a textünk,
akkor az std::cmatch osztályt, ha pedig string, akkor az std::smatch osztályt használhatjuk.
1 2 3 4 5 6 7 8 91011121314151617181920212223
// C++ban megadhatunk R"( ... )" delimeterek közt "raw string literálokat" is,// ezeken belül nincs escapelés, így nem kell \\ -elnünk, mint Javában kellettstd::regextheRegex(R"(\s*((?:\S+(?:\s+\S+)*)?)\s*)" );stringtheText=" a whitespace duplaplusz nemjó ";// ebbe fognak kerülni a csoportokstd::smatchresults;// text, match, regex a sorrend, ha illik, akkor feltölti a match-be a csoportokatif(std::regex_match(theText,results,theRegex)){// a match olyan kb. mint egy vector: van neki mérete cout<<"we have a match! Groups count: "<<results.size()<<endl;for(inti=0;i<results.size();i++){// és tömbelem-kiválasztás [] operátora is, visszaadja az i. csoportotcout<<"Group "<<i<<" is *"<<results[i]<<"*"<<endl;}}else{cerr<<"Sumthin is wrong";//should never happen, ez a regex mindenre illeszkedik}
Ennek a fenti hívásnak az eredményeképp megkapjuk, hogy két csoport van, a nulladikba került a teljes string,
az elsőbe pedig a a whitespace duplaplusz nemjó string.
Ha pedig valamiért char* az input:
1 2 3 4 5 6 7 8 9101112131415161718
std::regextheRegex(R"(\s*((?:\S+(?:\s+\S+)*)?)\s*)" );// most char* a textchar*theText=" a whitespace duplaplusz nemjó ";//ezért cmatch-ot használunkstd::cmatchresults;if(std::regex_match(theText,results,theRegex)){cout<<"we have a match! Groups count: "<<results.size()<<endl;for(inti=0;i<results.size();i++){cout<<"Group "<<i<<" is *"<<results[i]<<"*"<<endl;}}else{cerr<<"Sumthin is wrong";//should never happen, ez a regex mindenre illeszkedik}
Ha regex_match helyett a regex_search függvényt hívjuk, ez szintén egy boolt ad vissza,
hogy van-e az input textben az input regexre illeszkedő substring; ha igen, akkor az első
illeszkedő substringgel frissíti a paraméterként kapott match_resultot, ha kapott olyat:
1234567
regextheRegex("[+-]?\\d+");stringtheText("Ebben a szövegben 3 szám és 12 szó van, vagy még több");std::smatchresults;if(std::regex_search(theText,results,theRegex)){cout<<"Egy szám: "<<results[0]<<endl;// prints '3'}
Ha szeretnénk olyan funkcionalitást, amilyen pl. a grepnek van és megkeresni az összes illeszkedő
stringet, akkor pl. iterálhatjuk a regex_searchet úgy, hogy minden lépésben az input stringnek a
match utáni részére hívjuk (tehát ez nem olyan, mint a Java find(int i) metódusa).
Ezt a stringet állítja nekünk elő a match_results osztály suffix() függvénye:
12345678
regextheRegex("[+-]?\\d+");stringtheText("Ebben a szövegben 3 szám és 12 szó van, vagy -1 több");std::smatchresults;stringtempString=theText;// ne rontsuk szét az eredeti szövegetwhile(std::regex_search(tempString,results,theRegex)){cout<<"Egy szám: "<<results[0]<<endl;//prints '3', then prints '12', then prints -1tempString=results.suffix();}
Érdemes lehet tudni, hogy a fenti kód nem készít új másolatot a suffix() metódus hívásakor, az így készült
tempString ugyanannak stringnek a memóriaterületére fog mutatni. Maga a suffix() metódus nem is egy stringet
ad vissza, hanem egy referenciát egy olyan objektumra, melyből pl. az értékadás operátorral egy string objektumot
tud készíteni, de másolás nélkül.
A csomag sed-like regex alapú search&replace allt is támogat a std::regex_replace függvényen keresztül.
Ennek értelemszerű használatára egy példa:
1234
regextheRegex("[+-]?\\d+");// megint számjegyek, possibly előjellelstringtheText="Ebben a szövegben a 27 és a -42 fordulnak elő számként.";stringreplaced=std::regex_replace(theText,theRegex,"SZÁM");cout<<replaced<<endl;// prints Ebben a szövegben a SZÁM és a SZÁM fordulnak elő számként.
Ha nem pont ez a szándékunk, akkor flagekkel
módosítható a működés: pl. a format_first_only flag beállításával csak az első előfordulást cseréljük:
12345678
regextheRegex("[+-]?\\d+");//megint számjegyek, possibly előjellel, két csoportbanstringtheText="Ebben a szövegben a 27 és a -42 fordulnak elő számként.";stringreplaced=std::regex_replace(theText,// miben cseréljentheRegex,// a regexre illőt"SZÁM",// mire cseréljenstd::regex_constants::format_first_only);// flagek, logikai vagyolvacout<<replaced<<endl;// prints Ebben a szövegben a SZÁM és a -42 fordulnak elő számként.
A string, melyre cserélünk, tartalmazhatja még a következőket:
a $& jelzi magát a matchelt substringet
a $` jelzi a stringnek a match előtti részét (note: replaceAll hívásakor ez az előző match és az aktuális match
közti rész lesz)
a $' a stringnek a match utáni részét (note: ez aposztróf, az előző meg backtick)
a $0, $1, stb. pedig a nulladik, első stb. capturing group tartalmát.
Így pl. ez a kód zárójelbe teszi az input szövegben a számok előjel utáni részét:
1234
regextheRegex("([+-]?)(\\d+)" );stringtheText="Ebben a szövegben a 27 és a -42 fordulnak elő számként.";stringreplaced=std::regex_replace(theText,theRegex,"$1($2)");cout<<replaced<<endl;// prints Ebben a szövegben a (27) és a -(42) fordulnak elő számként.
Írjunk regexet, mely pontosan akkor illeszkedik egy input sorra, ha benne páros soka betű szerepel. (Ehhez talán először rajzoljunk egy automatát,
aztán ezt konvertáljuk algoritmussal regexbe.)
Írjunk regexet, mely pontosan akkor illeszkedik egy input sorra, ha benne páros soka betű vagypáratlan sokb betű szerepel.
Írjunk regexet, mely pontosan akkor illeszkedik egy input sorra, ha benne páros soka betű éspáratlan sokb betű szerepel.
Az előzőekben megadott páros-páratlan regexek illesztési sebességét mérjük ki Javában és egreppel is oly módon, hogy
generáljunk egy nagy szöveges filet, sok hosszú sorral, melyekben random a, b és c betűk vannak
futtassuk le az illesztést a regexünkkel, melyet készítettünk
futtassunk le egy olyan programot, mely két egyszerűbb regex egymás utáni illesztésével végzi el a feladatot