Regex, replace all occurrences of a subgroup

I want to replace β€œall” occurrences of β€œa” in parenthesis with β€œb”.

I have:

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

It outputs:

 a(baa)a 

But I want:

 a(bbb)a 
+5
source share
4 answers

It seems the only right solution is to do two searches in the regular expression. One to extract the parenthesis substring, and then to execute the second regular expression in that string.

 std::string in = "a(aa)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; 

Input:

 a(aa)a( a ) a" 

Conclusion:

 a(bb)a( b ) a 
0
source

The following code is generalized. Supports PCRE , PCRE2 and stl regex libs

 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); jp8::RegexReplace& rp = re.initReplace(); rp.setSubject(s) .setReplaceWith(replace_with) .setBufferSize(s.length() * 2); if(!case_sensitive) rp.addPcre2Option(PCRE2_CASELESS); 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 } 
+2
source

I do not think you can do this directly with std::regex_replace ; it does not appear to be addressed in any of the relevant regex format specifications. However, you can just do something like this:

 std::string s = "a(aaa)a"; std::regex re("(.*\\()(a*)(\\).*)"); // Regex amended to capture all a 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 

Since all you really needed to know in addition to the match was how much b you had to put there.

+1
source

This will complete the task:

 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; 

Conclusion:

 a(aaa)a a(bbb)a 
0
source

Source: https://habr.com/ru/post/1208304/


All Articles