Основи на регулярните изрази в C ++

Regular Expression Basics C



Помислете за следното изречение в кавички:

- Ето го моят човек.

Този низ може да е вътре в компютъра и потребителят може да иска да знае дали има думата man. Ако има думата мъж, той може да иска да промени думата мъж на жена; така че низът да чете:







'Ето моята жена.'

Има много други желания като тези от потребителя на компютър; някои са сложни. Регулярният израз, съкратено, regex, е предмет на обработката на тези проблеми от компютъра. C ++ идва с библиотека, наречена regex. Така че, програма на C ++ за обработка на regex трябва да започне с:



#включва

#включва

използвайки пространство за имена std;

Тази статия обяснява основите на регулярните изрази в C ++.



Съдържание на статията

Основи на регулярното изразяване

Regex

Низ като Here is my man. по -горе е целевата последователност или целевия низ или просто, target. man, който се търси, е регулярен израз или просто regex.





Съчетаване

Съпоставянето се случва, когато се намира думата или фразата, която се търси. След съвпадение може да се извърши подмяна. Например, след като мъжът е разположен отгоре, той може да бъде заменен от жена.

Просто съвпадение

Следващата програма показва как се съчетава думата man.



#включва

#включва

използвайки пространство за имена std;

intглавен()
{

regex reg('човек');
ако (regex_search(- Ето го моят човек.,рег))
цена<< „съвпадение“ <<endl;
иначе
цена<< „не съвпада“ <<endl;

връщане 0;
}

Функцията regex_search () връща true, ако има съвпадение и връща false, ако няма съвпадение. Тук функцията приема два аргумента: първият е целевият низ, а вторият е regex обект. Самият регулярно изражение е „човек“, в двойни кавички. Първият израз във функцията main () формира regex обект. Regex е тип, а reg е regex обект. Изходът на горната програма е „съпоставен“, тъй като „man“ се вижда в целевия низ. Ако „man“ не беше видяно в целта, regex_search () щеше да върне false, а изходът щеше да бъде „not match“.

Изходът на следния код не съвпада:

regex reg('човек');
ако (regex_search('Ето моята работа.',рег))
цена<< „съвпадение“ <<endl;
иначе
цена<< „не съвпада“ <<endl;

Не съвпада, тъй като регулярният израз „man“ не може да бъде намерен в целия целеви низ, „Ето моето създаване“.

модел

Редовният израз, човек отгоре, е много прост. Регексерите обикновено не са толкова прости. Регулярните изрази имат метасимволи. Метасимволите са знаци със специално значение. Метасимволът е герой за героите. C ++ regex метасимволи са:

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

Регулярно изражение, със или без метасимволи, е модел.

Класове персонажи

Квадратни скоби

Моделът може да има знаци в квадратни скоби. С това определена позиция в целевия низ би съответствала на някой от знаците в квадратните скоби. Помислете за следните цели:

'Котката е в стаята.'

'Прилепът е в стаята.'

'Плъхът е в стаята.'

Регулярното изражение, [cbr] at би съответствало на cat в първата цел. Това би съответствало на прилепа във втората цел. Това би съответствало на плъх в третата цел. Това е така, защото котката, прилепът или плъхът започва с „c“ или „b“ или „r“. Следният кодов сегмент илюстрира това:

regex reg('[cbr] в');
ако (regex_search('Котката е в стаята.',рег))
цена<< „съвпадение“ <<endl;
ако (regex_search('Прилепът е в стаята.',рег))
цена<< „съвпадение“ <<endl;
ако (regex_search('Плъхът е в стаята.',рег))
цена<< „съвпадение“ <<endl;

Изходът е:

съвпадащи

съвпадащи

съвпадащи

Диапазон от знаци

Класът, [cbr] в шаблона [cbr], би съответствал на няколко възможни знака в целта. Тя би съответствала на „c“ или „b“ или „r“ в целта. Ако целта няма „c“ или „b“ или „r“, последвана от at, няма да има съвпадение.

Някои възможности като „c“ или „b“ или „r“ съществуват в диапазон. Диапазонът от цифри от 0 до 9 има 10 възможности, а моделът за това е [0-9]. Диапазонът от малки букви от a до z има 26 възможности и моделът за това е [a-z]. Диапазонът от главни букви от А до Я има 26 възможности и моделът за това е [А-Я]. - официално не е метасимвол, но в квадратни скоби би посочил диапазон. И така, следното произвежда съвпадение:

ако (regex_search(„ID6id“,регулярно изражение('[0-9]')))

цена<< „съвпадение“ <<endl;

Забележете как регулярният израз е конструиран като втори аргумент. Съответствието се случва между цифрата 6 в диапазона, от 0 до 9 и 6 в целта, ID6id. Горният код е еквивалентен на:

ако (regex_search(„ID6id“,регулярно изражение('[0123456789]')))

цена<< „съвпадение“ <<endl;

Следният код създава съвпадение:

charстр[] = „ID6iE“;

ако (regex_search(стр,регулярно изражение('[a-z]')))

цена<< „съвпадение“ <<endl;

Имайте предвид, че първият аргумент тук е низова променлива, а не низов литерал. Съответствието е между „i“ в [a-z] и „i“ в ID6iE.

Не забравяйте, че диапазонът е клас. Може да има текст вдясно от диапазона или вляво от диапазона в шаблона. Следният код създава съвпадение:

ако (regex_search(„ID2id е лична карта ',регулярно изражение('ID [0-9] id')))

цена<< „съвпадение“ <<endl;

Съответствието е между ID [0-9] id и ID2id. Останалата част от целевия низ е идентификатор, не съвпада в тази ситуация.

Както се използва в субекта на регулярния израз (регулярни изрази), думата клас всъщност означава набор. Тоест един от героите в комплекта трябва да съвпада.

Забележка: Тирето - е метасимвол само в квадратни скоби, показващ диапазон. Това не е метасимвол в регулярното изражение, извън квадратните скоби.

Отрицание

Клас, включващ диапазон, може да бъде отхвърлен. Тоест никой от знаците в набора (класа) не трябва да съвпада. Това е обозначено с метасимвола ^ в началото на модела на класа, точно след отварящата квадратна скоба. И така, [^0-9] означава съвпадение на знака в съответната позиция в целта, която не е никакъв знак в диапазона, от 0 до 9 включително. Така че следният код няма да даде съвпадение:

ако (regex_search('0123456789101112',регулярно изражение('[^ 0-9]')))

цена<< „съвпадение“ <<endl;

иначе

цена<< „не съвпада“ <<endl;

Цифра в диапазона от 0 до 9 може да бъде намерена във всяка от целевите позиции на низ, 0123456789101112 ,; така че няма съвпадение - отрицание.

Следният код създава съвпадение:

ако (regex_search(„ABCDEFGHIJ“,регулярно изражение('[^ 0-9]')))

цена<< „съвпадение“ <<endl;

В целта не може да се намери цифра, ABCDEFGHIJ ,; значи има съвпадение.

[a-z] е диапазон извън [^a-z]. И така [^a-z] е отрицанието на [a-z].

[A-Z] е диапазон извън [^A-Z]. И така [^A-Z] е отрицанието на [A-Z].

Съществуват и други отрицания.

Съответстващи празни пространства

‘’ Или t или r или n или f е знак за интервал. В следния код регулярното изражение n съвпада с „ n“ в целта:

ако (regex_search(- От първа линия. rнОт ред втори.,регулярно изражение('н')))

цена<< „съвпадение“ <<endl;

Съвпадение с който и да е празен знак

Моделът или класът, който съответства на всеки знак с интервал, е, [ t r n f]. В следния код ‘’ е съпоставен: ’’

ако (regex_search('едно две',регулярно изражение('[T rн f] ')))

цена<< „съвпадение“ <<endl;

Съвпадение с който и да е не-бял знак

Моделът или класът, който съответства на всеки знак, който не е бял интервал, е [^ t r n f]. Следният код създава съвпадение, тъй като в целта няма празно пространство:

ако (regex_search('1234abcd',регулярно изражение('[^T rн f] ')))

цена<< „съвпадение“ <<endl;

Периодът (.) В шаблона

Точката (.) В шаблона съответства на всеки знак, включително себе си, с изключение на n, в целта. Съответствие се произвежда в следния код:

ако (regex_search('1234abcd',регулярно изражение('.')))

цена<< „съвпадение“ <<endl;

В следния код няма съответстващи резултати, защото целта е n.

ако (regex_search('н',регулярно изражение('.')))

цена<< „съвпадение“ <<endl;

иначе

цена<< „не съвпада“ <<endl;

Забележка: В знаков клас с квадратни скоби точката няма специално значение.

Съответстващи повторения

Знак или група знаци могат да се появят повече от веднъж в целевия низ. Модел може да съответства на това повторение. Метасимволите,?, *, +И {} се използват за съвпадение на повторението в целта. Ако x е интересен знак в целевия низ, тогава метасимволите имат следните значения:

х*:означава съвпадение'х' 0или повече пъти,i.И.,произволен брой пъти

х+:означава съвпадение'х' 1или повече пъти,i.И.,поне веднъж

х? :означава съвпадение'х' 0или1 време

х{н,}:означава съвпадение'х'поне n или повече пъти.Забележказапетая.

х{н} :съвпада'х'точно n пъти

х{н,м}:съвпада'х'поне n пъти,но не повече от m пъти.

Тези метасимволи се наричат квантори.

Илюстрации

*

* Съответства на предходния знак или предходна група, нула или повече пъти. o* съвпада с „o“ в куче на целевия низ. Също така съвпада с oo в книгата и търсенето. Регулярното изражение, o* съвпада с boooo в Животното booooed .. Забележка: o* съвпада с копаене, където „o“ се случва на нула (или повече) време.

+

+ Съответства на предходния знак или предходна група, 1 или повече пъти. Сравнете го с нула или повече пъти за *. Така че regex, e+ съвпада с „e“ в eat, където „e“ се появява веднъж. e+ също съответства на ee при овце, където „e“ се среща повече от един път. Забележка: e+ няма да съвпада с dig, защото в dig „e“ не се среща поне веднъж.

?

The? съответства на предходния знак или предходна група, 0 или 1 път (и не повече). И така, д? съвпада с dig, защото „e“ се среща в dig, нулев час. д? съвпада, защото ‘e’ се среща в set, еднократно. Забележка: д? все още съвпада с овце; въпреки че в овцете има две „е“. Тук има един нюанс - вижте по -късно.

{н,}

Това съответства на поне n последователни повторения на предходен знак или предходна група. Така че регулярното изражение, e {2,} съвпада с двете „е“ в целта, овце, и трите „е“ в целевата овца. e {2,} не съвпада с множеството, защото наборът има само едно „e“.

{н}

Това съвпада точно с n последователни повторения на предходен знак или предходна група. Така че регулярното изражение, e {2} съвпада с двете „e“ в целта, овце. e {2} не съвпада с набор, защото наборът има само едно „e“. Е, {2} съвпада с две „е“ в целта, овце. Тук има един нюанс - вижте по -късно.

{n, m}

Това съвпада с няколко последователни повторения на предходен знак или предходна група, навсякъде от n до m включително. И така, e {1,3} не съвпада с нищо в dig, което няма „e“. Той съвпада с едно „е“ в комплекта, двете „е в овце“, трите „е в овце“ и три „е в овце“. В последния мач има нюанс - вижте по -късно.

Съответстваща алтернатива

Помислете за следния целеви низ в компютъра.

Фермата има прасета с различни размери.

Програмистът може да иска да знае дали тази цел има коза, заек или прасе. Кодът ще бъде следният:

charстр[] = 'Фермата има прасета с различни размери.';

ако (regex_search(стр,регулярно изражение('коза | заек | прасе')))

цена<< „съвпадение“ <<endl;

иначе

цена<< „не съвпада“ <<endl;

Кодът създава съвпадение. Обърнете внимание на използването на символа за редуване, |. Може да има две, три, четири и повече опции. C ++ първо ще се опита да съпостави първата алтернатива, goat, на всяка позиция на символа в целевия низ. Ако не успее с коза, опитва следващата алтернатива, заек. Ако не успее със заек, той опитва следващата алтернатива, прасе. Ако свинята се провали, тогава C ++ преминава към следващата позиция в целта и започва отново с първата алтернатива.

В горния код свинята е съпоставена.

Съвпадение Начало или Край

Начало


Ако ^ е в началото на регулярното изражение, тогава началният текст на целевия низ може да бъде съпоставен с регулярното изражение. В следния код началото на целта е abc, което е съпоставено:

ако (regex_search('abc и def',регулярно изражение('^ abc')))

цена<< „съвпадение“ <<endl;

Не се извършва съвпадение в следния код:

ако (regex_search('Да, abc и def',регулярно изражение('^ abc')))

цена<< „съвпадение“ <<endl;

иначе

цена<< „не съвпада“ <<endl;

Тук abc не е в началото на целта.

Забележка: Циркумфлексният символ „^“ е метасимвол в началото на регулярното изражение, съответстващ на началото на целевия низ. Той все още е метасимвол в началото на класа знаци, където отрича класа.

Край

Ако $ е в края на регулярното изражение, тогава крайният текст на целевия низ може да бъде съпоставен с регулярното изражение. В следния код краят на целта е xyz, който е съчетан:

ако (regex_search('uvw и xyz',регулярно изражение('xyz $')))

цена<< „съвпадение“ <<endl;

Не се извършва съвпадение в следния код:

ако (regex_search('uvw и xyz финал',регулярно изражение('xyz $')))

цена<< „съвпадение“ <<endl;

иначе

цена<< „не съвпада“ <<endl;

Тук xyz не е в края на целта.

Групиране

Скобите могат да се използват за групиране на знаци в модел. Помислете за следното регулярно изражение:

'концерт (пианист)'

Групата тук е пианистка, заобиколена от метасимволите (и). Това всъщност е подгрупа, докато концерт (пианист) е цялата група. Помислете за следното:

'(Пианистът е добър)'

Тук подгрупата или поднизата е, пианистът е добър.

Поднизове с общи части

Счетоводителят е човек, който се грижи за книгите. Представете си библиотека с счетоводител и рафт за книги. Да предположим, че един от следните целеви низове е в компютъра:

„Библиотеката има рафт с книги, който се възхищава.“;

'Ето го счетоводителя.';

„Счетоводителят работи с лавицата за книги.“;

Да приемем, че интересът на програмиста не е да знае кое от тези изречения е в компютъра. Все пак неговият интерес е да знае дали рафт или счетоводител присъства в какъвто и да е целеви низ в компютъра. В този случай неговото регулярно изражение може да бъде:

'рафт за книги | счетоводител.'

Използване на редуване.

Забележете, че книгата, която е обща за двете думи, е въведена два пъти, с двете думи в шаблона. За да избегнете двукратно въвеждане на книга, регулярното изражение би било по -добре да бъде написано като:

'книга (рафт | пазач)'

Тук групата, рафт | пазител Алтернативният метасимвол все още се използва, но не за две дълги думи. Той е използван за двете крайни части на двете дълги думи. C ++ третира група като цяло. Така че C ++ ще търси рафт или пазач, който идва веднага след книгата. Изходът на следния код е съпоставен:

charстр[] = 'Библиотеката има рафт с книги, който се възхищава.';

ако (regex_search(стр,регулярно изражение('книга (рафт | пазач)')))

цена<< „съвпадение“ <<endl;

книжната лавица, а не счетоводителят са съпоставени.

Icase и многоредови regex_constants

иказа

Съответствието по подразбиране е чувствително към регистъра. Въпреки това може да се направи чувствителен към регистър. За да постигнете това, използвайте константата regex :: icase, както в следния код:

ако (regex_search('Обратна връзка',регулярно изражение('фураж',регулярно изражение::иказа)))

цена<< „съвпадение“ <<endl;

Изходът е съпоставен. Така че обратната връзка с главни букви „F“ е съпоставена с емисия с малки букви „f“. regex :: icase е направен вторият аргумент на конструктора regex (). Без това изявлението няма да доведе до съвпадение.

Многоредови

Помислете за следния код:

charстр[] = 'ред 1нред 2нред 3 ';

ако (regex_search(стр,регулярно изражение('^. * $')))

цена<< „съвпадение“ <<endl;

иначе

цена<< „не съвпада“ <<endl;

Изходът не съвпада. Регулярното изражение, ^.*$, Съвпада с целевия низ от началото до края му. .* означава всеки знак освен n, нула или повече пъти. Така че поради символите на нов ред ( n) в целта няма съвпадение.

Целта е многоредов низ. За да може „.“ Да съответства на символа на новия ред, трябва да се направи константата regex :: multiline, вторият аргумент на конструкцията regex (). Следният код илюстрира това:

charстр[] = 'ред 1нред 2нред 3 ';

ако (regex_search(стр,регулярно изражение('^. * $',регулярно изражение::многоредови)))

цена<< „съвпадение“ <<endl;

иначе

цена<< „не съвпада“ <<endl;

Съответствие на целия целеви низ

За да съответства на целия целеви низ, който няма символа за нов ред ( n), може да се използва функцията regex_match (). Тази функция е различна от regex_search (). Следният код илюстрира това:

charстр[] = „първа втора трета“;

ако (regex_match(стр,регулярно изражение('.*секунда.*')))

цена<< „съвпадение“ <<endl;

Тук има съвпадение. Имайте предвид обаче, че регулярното изражение съвпада с целия целеви низ и целевият низ не съдържа „ n“.

Обектът match_results

Функцията regex_search () може да приема аргумент между целта и обекта на regex. Този аргумент е обектът match_results. Целият съвпадащ (част) низ и съответните поднизове могат да бъдат известни с него. Този обект е специален масив с методи. Типът обект match_results е cmatch (за низови литерали).

Получаване на мачове

Помислете за следния код:

charстр[] = 'Жената, която търсехте!';

cmatch m;

ако (regex_search(стр,м,регулярно изражение('w.m.n')))

цена<<м[0] <<endl;

Целевият низ съдържа думата жена. Резултатът е жена ', което съответства на регулярното изражение, w.m.n. При нулев индекс специалният масив съдържа единственото съвпадение, което е жена.

С опциите за клас, само първият подниза, намерен в целта, се изпраща към специалния масив. Следният код илюстрира това:

cmatch m;

ако (regex_search('Плъхът, котката, прилепът!',м,регулярно изражение(„[bcr] в“)))

цена<<м[0] <<endl;

цена<<м[1] <<endl;

цена<<м[2] <<endl;

Изходът е плъх от индекс нула. m [1] и m [2] са празни.

При алтернативи, само първият подниза, намерен в целта, се изпраща към специалния масив. Следният код илюстрира това:

ако (regex_search(„Заекът, козата, прасето!“,м,регулярно изражение('коза | заек | прасе')))

цена<<м[0] <<endl;

цена<<м[1] <<endl;

цена<<м[2] <<endl;

Изходът е заек от индекс нула. m [1] и m [2] са празни.

Групиране

Когато са включени групи, пълният модел съвпада, отива в клетка нула на специалния масив. Следващият намерен подниза отива в клетка 1; следващият подниза преминава в клетка 2; и така нататък. Следният код илюстрира това:

ако (regex_search(„Най -добрият продавач на книги днес!“,м,регулярно изражение('книга ((sel) (ler))')))

цена<<м[0] <<endl;

цена<<м[1] <<endl;

цена<<м[2] <<endl;

цена<<м[3] <<endl;

Изходът е:

книжар

продавач

клетка

Прочети

Обърнете внимание, че групата (продавач) е преди групата (сел).

Позиция на мача

Позицията на съвпадение за всеки подниза в масива cmatch може да бъде известна. Преброяването започва от първия знак на целевия низ, на позиция нула. Следният код илюстрира това:

cmatch m;

ако (regex_search(„Най -добрият продавач на книги днес!“,м,регулярно изражение('книга ((sel) (ler))')))

цена<<м[0] << '->' <<м.позиция(0) <<endl;

цена<<м[1] << '->' <<м.позиция(1) <<endl;

цена<<м[2] << '->' <<м.позиция(2) <<endl;

цена<<м[3] << '->' <<м.позиция(3) <<endl;

Забележете използването на свойството position с индекса на клетката като аргумент. Изходът е:

книжар->5

продавач->9

клетка->9

Прочети->12

Търсене и замяна

Нова дума или фраза може да замени съвпадението. За това се използва функцията regex_replace (). Този път обаче низът, където се извършва подмяната, е низовият обект, а не низалният литерал. Така че библиотеката с низове трябва да бъде включена в програмата. Илюстрация:

#включва

#включва

#включва

използвайки пространство за имена std;

intглавен()
{
низ str= - Ето, идва моят човек. Ето го вашият човек.;
низ newStr=regex_replace(стр,регулярно изражение('човек'), 'жена');
цена<<newStr<<endl;

връщане 0;
}

Кодираната тук функция regex_replace () замества всички съвпадения. Първият аргумент на функцията е целта, вторият е regex обект, а третият е низът за замяна. Функцията връща нов низ, който е целта, но има замяна. Изходът е:

Идва моята жена. Ето я твоята жена.

Заключение

Регулярният израз използва шаблони за съвпадение на поднизове в низа на целевата последователност. Моделите имат метасимволи. Често използваните функции за C ++ регулярни изрази са: regex_search (), regex_match () и regex_replace (). Регулярното изражение е модел в двойни кавички. Тези функции обаче приемат regex обекта като аргумент, а не само regex. Регулярното изражение трябва да се превърне в регекс обект, преди тези функции да могат да го използват.