C ++

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

Основы регулярных выражений в C ++
Рассмотрим следующее предложение в кавычках:

"Вот мой мужчина."

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

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

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

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

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

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

  • Основы регулярных выражений
  • Шаблон
  • Классы персонажей
  • Соответствие пробелов
  • Период (.) в шаблоне
  • Соответствующие повторения
  • Соответствующее чередование
  • Соответствие началу или концу
  • Группировка
  • Icase и многострочные regex_constants
  • Соответствие всей цели
  • Объект match_results
  • Позиция матча
  • Искать и заменить
  • Заключение

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

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

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

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

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

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

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

#включать
#включать
используя пространство имен std;
int main ()

регулярное выражение reg ("человек");
if (regex_search ("Вот мой мужчина.", рег))
cout << "matched" << endl;
еще
cout << "not matched" << endl;
возврат 0;

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

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

регулярное выражение reg ("человек");
if (regex_search ("Вот моя работа.", рег))
cout << "matched" << endl;
еще
cout << "not matched" << endl;

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

Шаблон

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

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

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

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

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

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

"Кот в комнате."
"Летучая мышь в комнате."
"Крыса в комнате."

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

регулярное выражение reg ("[cbr] at");
if (regex_search ("Кот в комнате.", рег))
cout << "matched" << endl;
if (regex_search ("Летучая мышь в комнате.", рег))
cout << "matched" << endl;
if (regex_search ("Крыса в комнате.", рег))
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]. - официально не является метасимволом, но в квадратных скобках он указывает на диапазон. Итак, следующее дает совпадение:

если (regex_search ("ID6id", regex ("[0-9]")))
cout << "matched" << endl;

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

если (regex_search ("ID6id", regex ("[0123456789]")))
cout << "matched" << endl;

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

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

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

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

если (regex_search ("ID2id это идентификатор ", регулярное выражение (" ID [0-9] id ")))
cout << "matched" << endl;

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

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

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

Отрицание

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

если (regex_search ("0123456789101112", regex ("[^ 0-9]")))
cout << "matched" << endl;
еще
cout << "not matched" << endl;

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

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

если (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 ("один два", regex ("[\ t \ r \ n \ f]")))
cout << "matched" << endl;

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

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

если (regex_search ("1234abcd", regex ("[^ \ t \ r \ n \ f]")))
cout << "matched" << endl;

Период (.) в шаблоне

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

если (regex_search ("1234abcd", regex (".")))
cout << "matched" << endl;

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

если (regex_search ("\ n", regex (".")))
cout << "matched" << endl;
еще
cout << "not matched" << endl;

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

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

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

x *: означает совпадение 'x' 0 или более раз, i.е., любое количество раз
x +: означает совпадение 'x' 1 или более раз, i.е., Хотя бы один раз
Икс? : означает совпадение '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» в «The animal booooed».”. Примечание: «o *» соответствует «dig», где «o» встречается ноль (или более) раз.

+

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

?

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

n,

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

n

Это соответствует ровно n последовательным повторениям предыдущего символа или предыдущей группы. Таким образом, регулярное выражение «e 2» соответствует двум буквам «e» в целевом значении «овца». «E 2» не соответствует «set», потому что «set» имеет только одну букву «e». Что ж, «е 2» соответствует двум буквам «е» в цели «овца». Тут есть нюанс - см. Позже.

n, m

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

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

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

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

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

char str [] = "На ферме есть свиньи разных размеров.";
если (regex_search (str, regex ("коза | кролик | свинья")))
cout << "matched" << endl;
еще
cout << "not matched" << endl;

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

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

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

Начало


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

если (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», что соответствует:

если (regex_search ("uvw и xyz", regex ("xyz $")))
cout << "matched" << endl;

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

если (regex_search ("uvw и xyz final", regex ("xyz $")))
cout << "matched" << endl;
еще
cout << "not matched" << endl;

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

Группировка

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

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

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

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

Здесь подгруппа или подстрока - «пианист хороший».

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

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

"В библиотеке есть книжная полка, которой восхищаются.";
"Вот бухгалтер.";
"Бухгалтер работает с книжной полкой.";

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

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

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

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

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

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

char str [] = "В библиотеке есть книжная полка, которая вызывает восхищение.";
если (regex_search (str, regex ("книга (полка | хранитель)")))
cout << "matched" << endl;

«Книжная полка», а не «бухгалтер» были сопоставлены.

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

icase

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

if (regex_search ("Обратная связь", regex ("feed", regex :: icase)))
cout << "matched" << endl;

Результат «совпадает». Таким образом, «Feedback» с заглавной буквой «F» соответствует «feed» со строчной буквой F. «Regex :: icase» был сделан вторым аргументом конструктора regex (). Без этого оператор не дал бы совпадения.

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

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

char str [] = "строка 1 \ nстрока 2 \ nстрока 3";
если (regex_search (str, regex ("^.* $ ")))
cout << "matched" << endl;
еще
cout << "not matched" << endl;

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

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

char str [] = "строка 1 \ nстрока 2 \ nстрока 3";
если (regex_search (str, regex ("^.* $ ", регулярное выражение :: многострочное)))
cout << "matched" << endl;
еще
cout << "not matched" << endl;

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

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

char str [] = "первая вторая третья";
если (regex_match (str, regex (".*второй.* ")))
cout << "matched" << endl;

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

Объект match_results

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

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

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

char str [] = "Женщина, которую вы искали!";
cmatch m;
если (regex_search (str, m, regex ("w.м.п ")))
cout << m[0] << endl;

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

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

cmatch m;
if (regex_search ("Крыса, кошка, летучая мышь!", m, regex (" [bcr] at ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

Результатом будет «крыса» с нулевого индекса. m [1] и m [2] пусты.

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

if (regex_search ("Кролик, коза, свинья!", м, регулярное выражение (" коза | кролик | свинья ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

Результатом будет «кролик» с нулевого индекса. m [1] и m [2] пусты.

Группировки

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

if (regex_search ("Лучший продавец книг сегодня!", m, regex (" book ((sel) (ler)) ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;

Результат:

книготорговец
продавец
сел
лер

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

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

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

cmatch m;
if (regex_search ("Лучший продавец книг сегодня!", 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;

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

Книготорговец-> 5
продавец-> 9
сел-> 9
ler-> 12

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

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

#включать
#включать
#включать
используя пространство имен std;
int main ()

string str = "А вот и мой мужчина. Вот идет твой мужчина.";
строка newStr = regex_replace (str, regex ("мужчина"), "женщина");
cout << newStr << endl;
возврат 0;

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

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

Заключение

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

Как изменить левую и правую кнопки мыши на ПК с Windows 10
Совершенно нормально, что все устройства компьютерной мыши эргономичны для правшей. Но есть мышиные устройства, специально разработанные для левшей ил...
Эмуляция щелчков мыши с помощью мыши без щелчка в Windows 10
Использование мыши или клавиатуры в неправильной позе или чрезмерное использование может привести к множеству проблем со здоровьем, включая растяжение...
Добавьте жесты мыши в Windows 10 с помощью этих бесплатных инструментов
В последние годы компьютеры и операционные системы сильно эволюционировали. Было время, когда пользователям приходилось использовать команды для навиг...