Использование уже определенного шаблона регулярных выражений в другом шаблоне регулярных выражений и вопрос о применении регулярных выражений к файлу

#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 Что-то в этом роде. 🙂 По крайней мере, принцип, лежащий в основе обходного пути, должен быть ясен.