Regex работает только при первом появлении? - PullRequest
0 голосов
/ 07 августа 2020

Обновление: пожалуйста, прочтите мой комментарий к ответу jignatius

Я написал следующий код, чтобы найти определенные c совпадения в строке с использованием регулярного выражения и удалить их и заменить другим значением, но он работает не так, как ожидалось. Например, учитывая следующий ввод:

f={a,b}+{c,d}

, я ожидал бы, что он удалит как {a,b}, так и {c,d}, но он работает только с первым, что не так с моим кодом?

После некоторой проверки я вижу, что первый l oop вводится только один раз, но почему?

1 Ответ

1 голос
/ 07 августа 2020

В заголовке <regex> есть стандартная библиотечная функция std::regex_replace, которая выполняет то, что нужно: замену текста на основе регулярного выражения. Это значительно упростит вам задачу вместо использования созданного вручную l oop.

Вам просто нужно указать входную строку, регулярное выражение для сопоставления и заменяющую строку:

#include <iostream>
#include <regex>
#include <string>

int main()
{
    std::regex reg(R"(\{[^}]*\})");
    std::string mystring = "f={a,b}+{c,d}";
    auto newstring = std::regex_replace(mystring, reg, "title");
    std::cout << newstring;  //f=title+title
}

Примечание: также проще использовать необработанный строковый литерал в формате R"(literal)", чтобы избежать использования двойных обратных косых черт для экранирования специальных символов в регулярном выражении.

Demo


В своем комментарии вы говорите, что текст замены может меняться. В этом случае вам нужно будет выполнить al oop, а не прямую замену регулярного выражения.

Вы можете использовать std::regex_iterator, прямой итератор только для чтения, который будет вызывать std::regex_search() для вас. Вы можете использовать поток строк для создания новой строки:

#include <iostream>
#include <regex>
#include <string>
#include <sstream>

int main()
{
    std::regex reg(R"(\{[^}]*\})");
    std::string mystring = "f={a,b}+{c,d} + c";
        
    std::vector<std::string> replacements = { "rep1", "rep2", "rep3" };
    int i = 0;
    auto start = std::sregex_iterator(mystring.begin(), mystring.end(), reg);
    auto end = std::sregex_iterator{};
    std::ostringstream ss;

    for (std::sregex_iterator it = start; it != end; ++it)
    {
         std::smatch mat = *it;
         ss << mat.prefix() << replacements[i++];

         //If last match, stream suffix
         if (std::next(it) == end)
         {
             ss << mat.suffix();
         }
    }
    std::cout << ss.str();  //f=rep1+rep2 + c
}

Обратите внимание, что метод prefix() объекта std::smatch даст вам подстроку от целевой строки до начала совпадения. Затем вы помещаете замещающий текст в поток. Наконец, вы должны использовать метод suffix() объекта std::smatch для потоковой передачи любого конечного текста между последним совпадением и концом целевой строки.

Demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...