C ++

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

Основи на регулярния израз в C ++
Помислете за следното изречение в кавички:

„Ето го моят човек."

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

„Ето моята жена."

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

#include
#include
използване на пространство от имена std;

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

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

  • Основи на регулярния израз
  • модел
  • Класове на знаци
  • Съвпадение на бели пространства
  • Периодът (.) в модела
  • Съвпадащи повторения
  • Съответстваща редуване
  • Съвпадение Начало или Край
  • Групиране
  • Icase и многоредови regex_constants
  • Съвпадение на цялата цел
  • Match_results Обект
  • Позиция на мача
  • Търсене и замяна
  • Заключение

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

Regex

Струна като „Ето моя човек.”По-горе е целевата последователност или целевият низ или просто, target. „Човек“, който е търсен, е регулярният израз, или просто, регулярно изражение.

Съчетаване

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

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

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

#include
#include
използване на пространство от имена std;
int main ()

regex reg ("човек");
if (regex_search ("Тук е моят човек.", reg))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;
връщане 0;

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

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

regex reg ("човек");
if (regex_search ("Ето моята работа.", reg))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

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

модел

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

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

Регексът, със или без метасимволи, е модел.

Класове на знаци

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

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

„Котката е в стаята."
„Бухалката е в стаята."
„Плъхът е в стаята."

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

regex reg ("[cbr] at");
if (regex_search ("Котката е в стаята.", reg))
Cout << "matched" << endl;
if (regex_search ("Прилепът е в стаята.", reg))
Cout << "matched" << endl;
if (regex_search ("Плъхът е в стаята.", reg))
Cout << "matched" << endl;

Резултатът е:

съвпадащи
съвпадащи
съвпадащи

Обхват на символите

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

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

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

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

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

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

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

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

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

if (regex_search ("ID2id е ID ", регулярно изражение (" ID [0-9] id ")))
Cout << "matched" << endl;

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

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

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

Отрицание

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

if (regex_search ("0123456789101112", regex ("[^ 0-9]")))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

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

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

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

Не може да бъде намерена цифра в целта „ABCDEFGHIJ“; така че има съвпадение.

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

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

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

Съвпадение на бели пространства

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

if (regex_search ("На ред първи.\ r \ nОт втори ред.", регулярно изражение (" \ n ")))
Cout << "matched" << endl;

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

Шаблонът или класът, който да съответства на всеки празен знак, е [\ t \ r \ n \ f]. В следния код „се съчетава“:

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

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

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

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

Периодът (.) в модела

Периодът (.) в модела съвпада с всеки символ, включително себе си, с изключение на \ n, в целта. Съвпадение се създава в следния код:

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

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

if (regex_search ("\ n", regex (".")))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

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

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

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

x *: означава съвпадение на 'x' 0 или повече пъти, т.е.д., произволен брой пъти
x +: означава съвпадение на 'x' 1 или повече пъти, т.е.д., поне веднъж
х? : означава съвпадение 'x' 0 или 1 път
x n,: означава съвпадение на 'x' поне n или повече пъти. Обърнете внимание на запетая.
x n: съвпада с 'x' точно n пъти
x n, m: съвпада с 'x' поне n пъти, но не повече от m пъти.

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

Илюстрации

*

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

+

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

?

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

н,

Това съвпада с поне n последователни повторения на предходен знак или предходна група. Така че регулярният израз „e 2,“ съответства на двете „е“ в целта „овца“ и трите „е“ в целевата „овца“. „E 2,“ не съвпада с „set“, тъй като „set“ има само едно „e“.

н

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

n, m

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

Съответстваща редуване

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

„Фермата има свине с различни размери.”

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

char str [] = "Фермата има свине с различни размери.";
if (regex_search (str, regex ("коза | заек | прасе))))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

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

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

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

Начало


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

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

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

if (regex_search ("Да, abc и def", regex ("^ abc")))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

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

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

Край

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

if (regex_search ("uvw and xyz", regex ("xyz $")))
Cout << "matched" << endl;

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

if (regex_search ("uvw и xyz окончателен", regex ("xyz $")))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

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

Групиране

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

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

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

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

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

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

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

„Библиотеката разполага с рафт за книги, който се възхищава.";
„Ето го счетоводителят.";
„Счетоводителят работи с лавицата.";

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

"лавица за книги | счетоводител."

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

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

"книга (рафт | пазител)"

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

char str [] = "Библиотеката има рафт за книги, който се възхищава.";
if (regex_search (str, regex ("книга (рафт | пазач)")))
Cout << "matched" << endl;

„Рафт с книги“, а не „счетоводител“ са съвпадали.

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

icase

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

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

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

Многоредова

Обмислете следния код:

char str [] = "ред 1 \ n ред 2 \ n ред 3";
if (regex_search (str, regex ("^.* $ ")))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

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

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

char str [] = "ред 1 \ n ред 2 \ n ред 3";
if (regex_search (str, regex ("^.* $ ", регулярно изражение :: многоредово)))
Cout << "matched" << endl;
друго
Cout << "not matched" << endl;

Съвпадение на целия целеви низ

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

char str [] = "първа втора трета";
if (regex_match (str, regex (".* второ.* ")))
Cout << "matched" << endl;

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

Match_results Обект

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

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

Обмислете следния код:

char str [] = "Жената, която търсихте!";
съвпадение m;
if (regex_search (str, m, regex ("w.м.н")))
Cout << m[0] << endl;

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

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

съвпадение m;
if (regex_search ("Плъхът, котката, прилепът!", m, регулярно изражение (" [bcr] в ")))
Cout << m[0] << endl;
Cout << m[1] << endl;
Cout << m[2] << endl;

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

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

if (regex_search ("Заекът, козата, прасето!", m, regex (" коза | заек | прасе ")))
Cout << m[0] << endl;
Cout << m[1] << endl;
Cout << m[2] << endl;

Резултатът е „заек“ от нулев индекс. m [1] и m [2] са празни.

Групировки

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

if (regex_search ("Най - добрият продавач на книги днес!", m, регулярно изражение (" book ((sel) (ler)) ")))
Cout << m[0] << endl;
Cout << m[1] << endl;
Cout << m[2] << endl;
Cout << m[3] << endl;

Резултатът е:

продавач на книги
продавач
разпродажба
лер

Имайте предвид, че групата (продавач) идва преди групата (sel).

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

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

съвпадение m;
if (regex_search ("Най - добрият продавач на книги днес!", m, регулярно изражение (" 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;

Обърнете внимание на използването на свойството position с индекса на клетката като аргумент. Резултатът е:

продавач на книги-> 5
продавач-> 9
sel-> 9
ler-> 12

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

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

#include
#include
#include
използване на пространство от имена std;
int main ()

string str = "Ето, идва моят човек. Там отива твоят човек.";
низ newStr = regex_replace (str, regex ("мъж"), "жена");
Cout << newStr << endl;
връщане 0;

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

„Ето, идва моята жена. Отива вашата жена.”

Заключение

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

Инсталирайте най-новата стратегия за игра OpenRA на Ubuntu Linux
OpenRA е Libre / Free Real Time стратегия за игра, която пресъздава ранните игри на Westwood като класическата Command & Conquer: Red Alert. Разпредел...
Инсталирайте най-новия Dolphin Emulator за Gamecube & Wii на Linux
Dolphin Emulator ви позволява да играете избраните от вас игри Gamecube & Wii на Linux Personal Computers (PC). Като безплатно достъпен и емулатор на...
Как да използвам GameConqueror Cheat Engine в Linux
Статията обхваща ръководство за използването на GameConqueror cheat engine в Linux. Много потребители, които играят игри под Windows, често използват ...