Основы регулярных выражений в C ++

Regular Expression Basics C



Рассмотрим следующее предложение в кавычках:

«Вот мой человек».

Эта строка может находиться внутри компьютера, и пользователь может захотеть узнать, есть ли в ней слово man. Если в нем есть слово «мужчина», он может захотеть заменить слово «мужчина» на слово «женщина»; так что строка должна читать:







«Вот моя женщина».

Есть много других подобных желаний со стороны пользователя компьютера; некоторые сложные. Регулярное выражение, сокращенно регулярное выражение, является предметом обработки этих проблем компьютером. C ++ поставляется с библиотекой regex. Итак, программа на C ++ для обработки регулярных выражений должна начинаться с:



#включают

#включают

используя пространство имен std;

В этой статье объясняются основы регулярных выражений в C ++.



Содержание статьи

Основы регулярных выражений

Регулярное выражение

Строка вроде Вот мой мужчина. выше - целевая последовательность, целевая строка или просто цель. man, которое искали, является регулярным выражением или просто regex.





Соответствие

Говорят, что совпадение происходит, когда слово или фраза, которые ищутся, найдены. После сопоставления может иметь место замена. Например, после того, как мужчина находится наверху, его можно заменить женщиной.

Простое соответствие

Следующая программа показывает, как сопоставляется слово «человек».



#включают

#включают

используя пространство имен std;

intглавный()
{

регулярное выражение reg('человек');
если (regex_search(«Вот мой человек».,рег))
Стоимость<< 'совпадает' <<конец;
еще
Стоимость<< 'не соответствует' <<конец;

возвращение 0;
}

Функция regex_search () возвращает true, если совпадение есть, и false, если совпадения нет. Здесь функция принимает два аргумента: первый - целевая строка, а второй - объект регулярного выражения. Само регулярное выражение - это «человек» в двойных кавычках. Первый оператор в функции main () формирует объект регулярного выражения. Regex - это тип, а reg - объект регулярного выражения. Вышеупомянутый вывод программы является «совпадающим», поскольку в целевой строке отображается «человек». Если бы «man» не было замечено в цели, regex_search () вернула бы false, и результат был бы «несоответствующим».

Вывод следующего кода не совпадает:

регулярное выражение reg('человек');
если (regex_search(«Вот мое творение».,рег))
Стоимость<< 'совпадает' <<конец;
еще
Стоимость<< 'не соответствует' <<конец;

Не найдено, потому что регулярное выражение «человек» не может быть найдено во всей целевой строке «Вот моя работа».

Шаблон

Регулярное выражение, показанное выше, очень простое. Регулярные выражения обычно не так просты. Регулярные выражения имеют метасимволы. Метасимволы - это символы со специальным значением. Метасимвол - это персонаж о персонажах. Метасимволы регулярных выражений C ++:

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

Регулярное выражение с метасимволами или без них - это шаблон.

Классы персонажей

Квадратных скобок

В шаблоне могут быть символы в квадратных скобках. При этом конкретная позиция в целевой строке будет соответствовать любому из символов квадратных скобок. Рассмотрите следующие цели:

«Кот в комнате».

«Летучая мышь в комнате».

«Крыса в комнате».

Регулярное выражение [cbr] at будет соответствовать cat в первой цели. Это совпадет с битой во второй мишени. Это совпадет с крысой в третьей мишени. Это потому, что слова «кошка», «летучая мышь» или «крыса» начинаются с «c», «b» или «r». Следующий фрагмент кода иллюстрирует это:

регулярное выражение reg('[cbr] в');
если (regex_search(«Кот в комнате».,рег))
Стоимость<< 'совпадает' <<конец;
если (regex_search(«Летучая мышь в комнате».,рег))
Стоимость<< 'совпадает' <<конец;
если (regex_search(«Крыса в комнате».,рег))
Стоимость<< 'совпадает' <<конец;

Результат:

совпадает

совпадает

совпадает

Диапазон символов

Класс [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]. - официально не является метасимволом, но в квадратных скобках указывает диапазон. Итак, следующее дает совпадение:

если (regex_search('ID6id',регулярное выражение('[0-9]')))

Стоимость<< 'совпадает' <<конец;

Обратите внимание, как было построено регулярное выражение в качестве второго аргумента. Совпадение происходит между цифрой 6 в диапазоне от 0 до 9 и 6 в целевом идентификаторе ID6id. Приведенный выше код эквивалентен:

если (regex_search('ID6id',регулярное выражение('[0123456789]')))

Стоимость<< 'совпадает' <<конец;

Следующий код дает совпадение:

символп[] знак равно 'ID6iE';

если (regex_search(п,регулярное выражение('[а-я]')))

Стоимость<< 'совпадает' <<конец;

Обратите внимание, что первым аргументом здесь является строковая переменная, а не строковый литерал. Соответствие между «i» в [a-z] и «i» в ID6iE.

Не забывайте, что диапазон - это класс. Текст может быть справа от диапазона или слева от диапазона в шаблоне. Следующий код дает совпадение:

если (regex_search('ID2id это ID ',регулярное выражение('ID [0-9] id')))

Стоимость<< 'совпадает' <<конец;

Соответствие между ID [0-9] id и ID2id. Остальная часть целевой строки, являющаяся идентификатором, не соответствует в этой ситуации.

Используемое в регулярном выражении subject (регулярные выражения) слово class фактически означает набор. То есть один из символов в наборе должен совпадать.

Примечание. Дефис - это метасимвол только в квадратных скобках, обозначающий диапазон. Это не метасимвол в регулярном выражении, кроме квадратных скобок.

Отрицание

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

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

Стоимость<< 'совпадает' <<конец;

еще

Стоимость<< 'не соответствует' <<конец;

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

Следующий код дает совпадение:

если (regex_search('ABCDEFGHIJ',регулярное выражение('[^ 0-9]')))

Стоимость<< 'совпадает' <<конец;

В целевом объекте 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(«Первой линии.р пВторой строки.,регулярное выражение(' п')))

Стоимость<< 'совпадает' <<конец;

Соответствие любому пробельному символу

Шаблон или класс для соответствия любому символу пробела: [ t r n f]. В следующем коде совпадает '':

если (regex_search('один два',регулярное выражение('[ тр п f] ')))

Стоимость<< 'совпадает' <<конец;

Соответствие любому непробельному символу

Шаблон или класс для соответствия любому символу, отличному от пробела, - [^ t r n f]. Следующий код дает совпадение, потому что в цели нет пробелов:

если (regex_search('1234abcd',регулярное выражение('[^ тр п f] ')))

Стоимость<< 'совпадает' <<конец;

Точка (.) В шаблоне

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

если (regex_search('1234abcd',регулярное выражение('.')))

Стоимость<< 'совпадает' <<конец;

В следующем коде совпадений нет, так как целью является n.

если (regex_search(' п',регулярное выражение('.')))

Стоимость<< 'совпадает' <<конец;

еще

Стоимость<< 'не соответствует' <<конец;

Примечание. Внутри класса символов с квадратными скобками точка не имеет особого значения.

Соответствующие повторения

Символ или группа символов могут встречаться в целевой строке более одного раза. Шаблон может соответствовать этому повторению. Метасимволы?, *, + И {} используются для соответствия повторению в цели. Если x - интересующий символ в целевой строке, то метасимволы имеют следующие значения:

Икс*:означает совпадение'Икс' 0или более раз,я.А также.,любое количество раз

Икс+:означает совпадение'Икс' 1или более раз,я.А также.,Хотя бы один раз

Икс? :означает совпадение'Икс' 0или1 время

Икс{п,}:означает совпадение'Икс'не менее n или более раз.Примечаниезапятая.

Икс{п} :соответствие'Икс'ровно n раз

Икс{п,м}:соответствие'Икс'как минимум n раз,но не более m раз.

Эти метасимволы называются кванторы.

Иллюстрации

*

* Соответствует предыдущему символу или предыдущей группе, ноль или более раз. o * совпадает с «o» в слове dog целевой строки. Это также соответствует oo в книге и ищет. Регулярное выражение o * соответствует boooo в The animal booooed .. Примечание: o * соответствует dig, где ‘o’ встречается ноль (или более) раз.

+

+ Соответствует предыдущему символу или предыдущей группе 1 или более раз. Сравните это с ноль или более раз для *. Таким образом, регулярное выражение e + соответствует 'e' в 'eat', где 'e' встречается один раз. e + также соответствует ee у овец, где 'e' встречается более одного раза. Примечание: e + не будет соответствовать dig, потому что в dig слово «e» не встречается хотя бы один раз.

?

? соответствует предыдущему символу или предыдущей группе, 0 или 1 раз (и не более). Итак, е? соответствует dig, потому что 'e' встречается в dig, нулевое время. е? соответствует набору, потому что 'e' встречается в наборе один раз. Примечание: e? все еще совпадает с овцами; хотя в овце есть два «е». Здесь есть нюанс - см. Позже.

{n,}

Это соответствует как минимум n последовательным повторениям предыдущего символа или предыдущей группы. Таким образом, регулярное выражение e {2,} соответствует двум буквам «е» в целевой овце и трем «е» в целевой овце. e {2,} не соответствует набору, потому что набор имеет только один 'e'.

{n}

Это соответствует ровно n последовательным повторениям предыдущего символа или предыдущей группы. Таким образом, регулярное выражение e {2} соответствует двум буквам 'e' в целевом объекте, 'овца'. e {2} не соответствует набору, потому что набор имеет только один 'e'. Что ж, e {2} совпадает с двумя буквами e в мишени, овца. Здесь есть нюанс - см. Позже.

{n, m}

Это соответствует нескольким последовательным повторениям предыдущего символа или предыдущей группы в любом месте от n до m включительно. Итак, e {1,3} ничего не соответствует в dig, в котором нет 'e'. Он соответствует одному 'е' в наборе, двум 'е' у овец, трем 'е' у овец и трем 'е' у овец. По последнему матчу есть нюанс - см. Позже.

Соответствующее чередование

Рассмотрим следующую целевую строку в компьютере.

На ферме есть свиньи разных размеров.

Программист может захотеть узнать, есть ли у этой цели коза, кролик или свинья. Код будет следующим:

символп[] знак равно «На ферме есть свиньи разных размеров».;

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

Стоимость<< 'совпадает' <<конец;

еще

Стоимость<< 'не соответствует' <<конец;

Код дает совпадение. Обратите внимание на использование символа чередования |. Вариантов может быть два, три, четыре и более. C ++ сначала попытается сопоставить первую альтернативу, goat, в каждой позиции символа в целевой строке. Если с козой не удается, она пробует следующую альтернативу - кролика. Если у кролика не получается, он пробует следующую альтернативу, свинью. Если pig терпит неудачу, C ++ переходит на следующую позицию в цели и снова начинает с первой альтернативы.

В приведенном выше коде совпадает свинья.

Соответствие началу или концу

Начало


Если ^ находится в начале регулярного выражения, тогда начальный текст целевой строки может совпадать с регулярным выражением. В следующем коде начало цели - abc, что соответствует:

если (regex_search('abc и def',регулярное выражение('^ abc')))

Стоимость<< 'совпадает' <<конец;

В следующем коде сопоставления не происходит:

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

Стоимость<< 'совпадает' <<конец;

еще

Стоимость<< 'не соответствует' <<конец;

Здесь abc находится не в начале цели.

Примечание. Символ циркумфлекса ‘^’ - это метасимвол в начале регулярного выражения, соответствующий началу целевой строки. Это все еще метасимвол в начале класса символов, где он отрицает класс.

Конец

Если $ находится в конце регулярного выражения, то конечный текст целевой строки может совпадать с регулярным выражением. В следующем коде концом цели является xyz, что соответствует:

если (regex_search('uvw и xyz',регулярное выражение('xyz $')))

Стоимость<< 'совпадает' <<конец;

В следующем коде сопоставления не происходит:

если (regex_search('uvw и xyz final',регулярное выражение('xyz $')))

Стоимость<< 'совпадает' <<конец;

еще

Стоимость<< 'не соответствует' <<конец;

Здесь xyz не находится в конце цели.

Группировка

Скобки можно использовать для группировки символов в шаблоне. Рассмотрим следующее регулярное выражение:

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

Группа здесь - пианист, окруженный метасимволами (и). Фактически это подгруппа, а концертная (пианистка) - это вся группа. Учтите следующее:

'(Пианист хороший)'

Здесь подгруппа или подстрока, пианист хорош.

Подстроки с общими частями

Бухгалтер - это человек, который заботится о книгах. Представьте себе библиотеку с бухгалтером и книжной полкой. Предположим, что на компьютере есть одна из следующих целевых строк:

'В библиотеке есть книжная полка, которая вызывает восхищение.';

'Вот бухгалтер.';

'Бухгалтер работает с книжной полкой.';

Предположим, что программиста не интересует, какое из этих предложений находится в компьютере. Тем не менее, его интересует, присутствует ли книжная полка или бухгалтер в какой-либо целевой строке в компьютере. В этом случае его регулярное выражение может быть:

'книжная полка | бухгалтер.'

Используя чередование.

Обратите внимание, что книга, которая является общей для обоих слов, была напечатана дважды в двух словах образца. Чтобы не печатать книгу дважды, регулярное выражение лучше записать как:

'книга (полка | хранитель)'

Здесь группа, полка | хранитель. Метасимвол чередования все еще используется, но не для двух длинных слов. Он использовался для двух конечных частей двух длинных слов. C ++ рассматривает группу как объект. Таким образом, C ++ будет искать полку или хранитель, который идет сразу после книги. Соответствует вывод следующего кода:

символп[] знак равно «В библиотеке есть книжная полка, которая вызывает восхищение».;

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

Стоимость<< 'совпадает' <<конец;

книжная полка, а не бухгалтер.

Icase и многострочные regex_constants

icase

По умолчанию при сопоставлении учитывается регистр. Однако его можно сделать нечувствительным к регистру. Для этого используйте константу regex :: icase, как в следующем коде:

если (regex_search('Обратная связь',регулярное выражение('кормить',регулярное выражение::icase)))

Стоимость<< 'совпадает' <<конец;

Выходные данные совпадают. Таким образом, обратная связь с заглавной буквой «F» была сопоставлена ​​фидом со строчной буквой «f». regex :: icase был сделан вторым аргументом конструктора regex (). Без этого утверждение не привело бы к совпадению.

Многострочный

Рассмотрим следующий код:

символп[] знак равно 'строка 1 пстрока 2 пстрока 3 ';

если (regex_search(п,регулярное выражение('^. * $')))

Стоимость<< 'совпадает' <<конец;

еще

Стоимость<< 'не соответствует' <<конец;

Выход не совпадает. Регулярное выражение ^. * $ Соответствует целевой строке от начала до конца. . * означает любой символ, кроме n, ноль или более раз. Итак, из-за символов новой строки ( n) в цели совпадения не было.

Цель - многострочная строка. Чтобы ‘.’ Соответствовал символу новой строки, необходимо создать константу regex :: multiline, второй аргумент конструкции regex (). Следующий код иллюстрирует это:

символп[] знак равно 'строка 1 пстрока 2 пстрока 3 ';

если (regex_search(п,регулярное выражение('^. * $',регулярное выражение::многострочный)))

Стоимость<< 'совпадает' <<конец;

еще

Стоимость<< 'не соответствует' <<конец;

Соответствие всей целевой строке

Чтобы соответствовать всей целевой строке, в которой нет символа новой строки ( n), можно использовать функцию regex_match (). Эта функция отличается от regex_search (). Следующий код иллюстрирует это:

символп[] знак равно 'первый второй третий';

если (regex_match(п,регулярное выражение('.*второй.*')))

Стоимость<< 'совпадает' <<конец;

Здесь есть совпадение. Однако обратите внимание, что регулярное выражение соответствует всей целевой строке, а в целевой строке нет символа « n».

Объект match_results

Функция regex_search () может принимать аргумент между целью и объектом регулярного выражения. Этот аргумент - объект match_results. С его помощью можно узнать всю согласованную строку (часть) и согласованные подстроки. Этот объект представляет собой специальный массив с методами. Тип объекта match_results - cmatch (для строковых литералов).

Получение совпадений

Рассмотрим следующий код:

символп[] знак равно «Женщина, которую вы искали!»;

cmatch m;

если (regex_search(п,м,регулярное выражение('w.m.n')))

Стоимость<<м[0] <<конец;

В целевой строке есть слово женщина. Результатом будет woman ’, что соответствует регулярному выражению w.m.n. По нулевому индексу специальный массив содержит единственное совпадение - женщину.

С параметрами класса только первая подстрока, найденная в цели, отправляется в специальный массив. Следующий код иллюстрирует это:

cmatch m;

если (regex_search(«Крыса, кошка, летучая мышь!»,м,регулярное выражение('[bcr] at')))

Стоимость<<м[0] <<конец;

Стоимость<<м[1] <<конец;

Стоимость<<м[2] <<конец;

На выходе получается крыса с нулевого индекса. m [1] и m [2] пусты.

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

если (regex_search(«Кролик, коза, свинья!»,м,регулярное выражение('коза | кролик | свинья')))

Стоимость<<м[0] <<конец;

Стоимость<<м[1] <<конец;

Стоимость<<м[2] <<конец;

На выходе получается кролик с нулевого индекса. m [1] и m [2] пусты.

Группировки

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

если (regex_search(«Лучший продавец книг сегодня!»,м,регулярное выражение('книга ((sel) (ler))')))

Стоимость<<м[0] <<конец;

Стоимость<<м[1] <<конец;

Стоимость<<м[2] <<конец;

Стоимость<<м[3] <<конец;

Результат:

книготорговец

продавец

клетка

читать

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

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

Позиция совпадения для каждой подстроки в массиве cmatch может быть известна. Подсчет начинается с первого символа целевой строки в нулевой позиции. Следующий код иллюстрирует это:

cmatch m;

если (regex_search(«Лучший продавец книг сегодня!»,м,регулярное выражение('книга ((sel) (ler))')))

Стоимость<<м[0] << '->' <<м.позиция(0) <<конец;

Стоимость<<м[1] << '->' <<м.позиция(1) <<конец;

Стоимость<<м[2] << '->' <<м.позиция(2) <<конец;

Стоимость<<м[3] << '->' <<м.позиция(3) <<конец;

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

книготорговец->5

продавец->9

клетка->9

читать->12

Искать и заменить

Новое слово или фраза могут заменить совпадение. Для этого используется функция regex_replace (). Однако на этот раз строка, в которой происходит замена, является строковым объектом, а не строковым литералом. Итак, в программу необходимо включить строковую библиотеку. Иллюстрация:

#включают

#включают

#включают

используя пространство имен std;

intглавный()
{
строка strзнак равно «Вот идет мой человек. Вот идет твой мужчина.;
строка newStrзнак равноregex_replace(п,регулярное выражение('человек'), 'женщина');
Стоимость<<newStr<<конец;

возвращение 0;
}

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

А вот и моя женщина. Вот идет твоя женщина.

Заключение

Регулярное выражение использует шаблоны для сопоставления подстрок в целевой строке последовательности. У шаблонов есть метасимволы. Обычно используемые функции для регулярных выражений C ++: regex_search (), regex_match () и regex_replace (). Регулярное выражение - это образец в двойных кавычках. Однако эти функции принимают в качестве аргумента объект регулярного выражения, а не только регулярное выражение. Регулярное выражение должно быть преобразовано в объект регулярного выражения, прежде чем эти функции смогут его использовать.