在std :: string上执行正则表达式搜索和替换

Tor*_*erk 4 c++ regex string search c++11

我有一个模式'"XYZ\d\d'和一个'较大'的字符串,这种模式可以多次出现.

我的目标是在字符串中找到模式的所有实例,然后用原始字符串中的字母"A"替换该匹配中的所有字符.

到目前为止我已经得到了以下内容,但是有一个错误:

#include <iostream>
#include <regex>

int main() {
    std::regex  exp("XYZ\\d\\d");
    std::smatch res;
    std::string str = " XYZ111 d-dxxxxxxx XYZ222 t-nyyyyyyyyy XYZ333 t-r ";

    auto itr = str.cbegin();

    while (std::regex_search(itr, str.cend(), res, exp)) {

        std::cout << "[" << res[0] << "]" << std::endl;

        for (auto j = res[0].first; j != res[0].second; ++j) {
           *j = 'A';  // Error as dereferencing j causes a const reference
        }

        itr += res.position() + res.length();
    }

    std::cout << std::endl;

    std::cout << "mod: " << str << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我不确定使用C++ 11 正则表达式工具完成任务时的正确过程是什么.

还有人想知道是否有类似regex_replace的东西需要一个仿函数,人们可以指定他们想要在每场比赛中改变比赛的方式?

Pet*_*erT 5

由于你有位置和长度你可以使用它来进行替换,或者如果你只是想摆脱错误,你可以std::match_results使用非const迭代器进行实例化(所有stdlib默认实例化都使用const).

#include <iostream>
#include <regex>

int main() {
    using strmatch = std::match_results<std::string::iterator>;

    std::regex  expr("XYZ\\d\\d");
    strmatch res;
    std::string str = " XYZ111 d-dxxxxxxx XYZ222 t-nyyyyyyyyy XYZ333 t-r ";

    auto itr = str.begin();

    while (std::regex_search(itr, str.end(), res, expr)) {

        std::cout << "[" << res[0] << "]" << std::endl;

        for (auto j = res[0].first; j != res[0].second; ++j) {
           *j = 'A';  // Error as dereferencing j causes a const reference
        }

        itr += res.position() + res.length();
    }

    std::cout << std::endl;

    std::cout << "mod: " << str << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*nko 5

您需要基于全局正则表达式的替换。这是在没有任何显式循环的情况下执行此操作的三种方法(确保正则表达式替换代码中存在“隐式”循环):

#include <iostream>
#include <string>
#include <regex> // std::regex
#include <pcrecpp.h> // pcrecpp::RE -- needs "-lpcrecpp -lpcre"
#include <pcrscpp.h> // pcrscpp::replace -- needs "-lpcrscpp -lpcre"

int main() {
    std::regex std_rx (R"del(XYZ\d\d)del");
    pcrecpp::RE pcrecpp_rx (R"del(XYZ\d\d)del");
    pcrscpp::replace pcrscpp_rs(R"del(s/XYZ\d\d/A/g)del");
    std::string str = " XYZ111 d-dxxxxxxx XYZ222 t-nyyyyyyyyy XYZ333 t-r ";

    std::cout << "std::regex way: " << std::regex_replace (str, std_rx, "A") << std::endl
              << "pcrecpp way: ";

    std::string buffer(str);
    pcrecpp_rx.GlobalReplace("A", &buffer);

    std::cout << buffer << std::endl
              << "pcrscpp way: ";

    pcrscpp_rs.replace_store(str);
    std::cout << pcrscpp_rs.replace_result << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果:

std::regex way:  A1 d-dxxxxxxx A2 t-nyyyyyyyyy A3 t-r
pcrecpp way:  A1 d-dxxxxxxx A2 t-nyyyyyyyyy A3 t-r
pcrscpp way:  A1 d-dxxxxxxx A2 t-nyyyyyyyyy A3 t-r
Run Code Online (Sandbox Code Playgroud)

std::regex需要 C++11 特性,并且在简单模式上的执行速度比 PCRE 慢两倍(参见这个答案),我预计在更复杂的模式上会更糟,但不需要任何额外的库,只要你使用 C++ 11 编译器。PCRECPP是由 Google 编写的PCRE C++ 包装器。PCRSCPP是我对 PCRE 的包装器,它提供了类似 Perl 的基于正则表达式的替换功能,因此在这个范围内比 PCRECPP 功能更丰富。