正则表达式,替换所有子组出现

7

我希望替换括号内所有的字母"a"为"b"。

我有:

std::string s = "a(aaa)a";
std::regex e("(\\(.*?)(a)(.*\\))");
s = std::regex_replace(s, e, "$1b$3");

std::cout << s << std::endl;

它的输出结果是:
a(baa)a

但是我希望:

a(bbb)a
4个回答

2
这个可以完成任务:
const std::string in = "a(aaa)a";
const std::regex re("(\\(.*?)(a)(.*\\))");

std::string out = in;
while (std::regex_search(out, re)) {
    out = std::regex_replace(out, re, "$1b$3");
}

std::cout << in << std::endl;
std::cout << out << std::endl;

输出:

a(aaa)a
a(bbb)a

2

以下代码是通用的。支持PCREPCRE2stl正则表达式库。

bool U::String::replaceExAll(string &s, const string& replace_this_reg_ex, const string& replace_with, bool case_sensitive, bool extended)
{
#ifdef UTIL_USE_PCRE
    pcrecpp::RE_Options options;
    options.set_utf8(true);
    options.set_caseless(!case_sensitive);
    pcrecpp::RE(replace_this_reg_ex, options).GlobalReplace(replace_with, &s);
    return true;
#elif UTIL_USE_PCRE2
    jp8::Regex re(replace_this_reg_ex);
    if(!case_sensitive)
            re.addPcre2Option(PCRE2_CASELESS).compile();

    jp8::RegexReplace& rp = re.initReplace();
    rp.setSubject(s)
                .setReplaceWith(replace_with)
                .setBufferSize(s.length() * 2);

    if(extended)
        rp.addPcre2Option(PCRE2_SUBSTITUTE_EXTENDED);
    rp.addPcre2Option(PCRE2_SUBSTITUTE_GLOBAL);
    // PCRE2_DOTALL PCRE2_MULTILINE PCRE2_UTF does not work

    s = rp.replace();
    return re.getErrorNumber() == 0;
#else
    regex rx = regex(replace_this_reg_ex, case_sensitive ? 0 : regex_constants::icase);;
    std:string temp = std::regex_replace(s, rx, replace_with);
    s = temp;

    return true;
#endif
}

如果要使用C++ PCRE2包装器,请使用以下库:JPCRE2


1
请格式化您的代码,不要使用new/delete。谢谢。 - over_optimistic
1
PCRE2_DOTALL、PCRE2_MULTILINE和PCRE2_UTF不起作用。如果将它们添加到RegexReplace对象中,它们将无法工作。这些是编译选项。正则表达式需要使用这些选项进行编译。 - Jahid

1

我不认为您可以直接使用std::regex_replace来完成这个任务;在相关的正则表达式格式规范中似乎没有涉及到这个问题。但是,您可以简单地执行以下操作:

std::string s = "a(aaa)a";
std::regex re("(.*\\()(a*)(\\).*)"); // Regex amended to capture all a's between ()
std::smatch m;

std::regex_search(s, m, re);
s = m.format("$1" + std::string(m[2].length(), 'b') + "$3"); // match length known here

既然除了比赛之外,你真正需要知道的只是需要在那里放多少个b。


1
聪明,但不完全是我想要的。我必须承认它涵盖了我的例子,但我需要一个解决方案,其中子组可以出现在括号的任何位置。 - Adelost

0

看起来唯一正确的解决方案是进行两个正则表达式搜索。一个用于提取括号子字符串,然后在该字符串上执行第二个正则表达式。

std::string in = "a(a a)a( a ) a";
std::regex re("\\(.*?\\)");
std::smatch m;
std::string out;
while (std::regex_search(in, m, re))
{
    out += m.prefix();
    std::regex re("a");
    out += std::regex_replace(m[0].str(), re, "b");
    in = m.suffix();
}
out += in;

std::cout << out << std::endl;

输入:

a(a a)a( a ) a"

输出:

a(b b)a( b ) a

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接