#c #regex #file
#c #регулярное выражение #файл
Вопрос:
Как я могу использовать уже определенный шаблон регулярных выражений в другом шаблоне регулярных выражений. Например, в следующем коде sign
и number
определены, и я хочу использовать их при определении relation
:
regex sign("=<|=|>|<=|<>|>=");
regex number("^[1-9]\d*");
regex relation(number, sign, number)
Итак, мне нужно найти все совпадения (с шаблоном типа 23<=34
или 123<>2000
) в данном файле.
Поскольку я не завершил relation
, я тестировал с sign
:
#include <iostream>
#include <fstream>
#include <regex>
using namespace std;
int main() {
regex sign("=<|=|>|<=|<>|>=");
regex digit("[0-9]");
regex number("^[1-9]\d*");
//regex relation("^[1-9]d*[=<|=|>|<=|<>|>=]^[1-9]d*"); (this part is what I couldn't do)
string line;
ifstream fin;
fin.open("name.txt");
if (fin.good()) {
while (getline(fin, line)) {
bool match_sign = regex_search(line, sign);
if (match_sign) {
cout << line << endl; // but I need to print the match only
}
}
}
return 0;
}
Когда я хочу распечатать совпадения в файле, он печатает всю строку, содержащую любое совпадение. Как я могу заставить его печатать только само совпадение, но не всю строку?
Обновить:
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>
using namespace std;
#define REGEX_SIGN "=<|=|>|<=|<>|>="
#define REGEX_DIGIT "[0-9]"
#define REGEX_NUMBER "^" REGEX_DIGIT "\d*"
int main() {
regex sign(REGEX_SIGN);
regex digit(REGEX_DIGIT);
regex number(REGEX_NUMBER);
regex relation(REGEX_NUMBER REGEX_SIGN REGEX_NUMBER);
string line, text;
ifstream fin;
fin.open("name.txt");
if (fin.good()) {
while (getline(fin, line)) {
text = line " ";
}
int count = 0;
string word = "";
for (int i = 0; i < text.length(); i ) {
if (text[i] == ' ') {
cout << "word = " << word << " | match: " << regex_match(word, relation) << endl;
if (regex_match(word, relation)) {
cout << word << endl;
}
word = "";
}
else {
word = text[i];
}
}
}
// cout << text << endl;
return 0;
}
Текущий name.txt
выглядит так:
Но я думаю, что регулярное выражение работает неправильно:
В нем говорится, что совпадений слов нет. В чем проблема?
Комментарии:
1. Что касается «что-то не так с обратной косой чертой d», вы должны помнить, что обратная косая черта в строках означает что-то особенное. Если вам нужна явная обратная косая черта внутри строки, вам нужно экранировать ее с помощью обратной косой черты или использовать «необработанные» строковые литералы.
2. @Someprogrammerdude Да, спасибо, ошибка исчезла после добавления еще одной обратной косой черты. Я обновлю вопрос с этим исправлением
3. Последняя строка может быть
R"(([1-9]d*)(<|<=|=|>|>=|<>)([1-9]d*))"
.
Ответ №1:
Проблема «повторного использования» меньшего регулярного выражения внутри большего регулярного выражения на самом деле невозможна.
Единственный обходной путь, который я вижу, — это определить строки регулярных выражений в виде макросов и использовать функцию конкатенации литеральных строк компиляторов для создания строк большего размера:
#define REGEX_SIGN "=<|=|>|<=|<>|>="
#define REGEX_DIGIT "[0-9]"
#define REGEX_NUMBER "^" REGEX_DIGIT "\d*"
regex sign(REGEX_SIGN);
regex digit(REGEX_DIGIT);
regex number(REGEX_NUMBER);
regex relation(REGEX_NUMBER REGEX_SIGN REGEX_NUMBER);
Это не повторное использование реальных regex
объектов, а только создание более длинных литеральных строк из меньших.
Комментарии:
1. Я обновил вопрос с помощью вашего скрипта, но по-прежнему кажется, что что-то работает неправильно. Я приложил скриншот вывода. Там должны быть первая и третья строки
match: 1
…2.
REGEX_SIGN
должно быть"(?:=<|=|>|<=|<>|>=)"
, чтобы разрешить значимую конкатенацию. и"^"
не должно быть вREGEX_NUMBER
3. @Jarod42 Что-то в этом роде. 🙂 По крайней мере, принцип, лежащий в основе обходного пути, должен быть ясен.