`re.sub(pattern, functor, string)` 用于 C++
Posted
技术标签:
【中文标题】`re.sub(pattern, functor, string)` 用于 C++【英文标题】:`re.sub(pattern, functor, string)` for C++ 【发布时间】:2014-09-20 05:56:39 【问题描述】:Python regexp 有一个有用的特性,即使用函数来确定替换的能力。也就是说,re.sub(pattern, functor, string)
会将匹配结果传递给仿函数以获取要使用的替换字符串。这比使用 `\1', '\2' 来引用子匹配的格式字符串语法灵活得多。
现在,我想在 C++ 中实现相同的目标,但我不知道该怎么做。第一个想法是使用std::regex_replace
,但它没有允许传递函子的重载。另一个想法是使用迭代器将文本拆分为类型为MATCH
或NOT_MATCH
的标记,但标准正则表达式迭代器似乎只返回一种类型。他们要么跳过所有不匹配,要么跳过所有匹配。
有什么办法吗?我更喜欢标准库。
【问题讨论】:
对于任何未来的读者,boost::regex
似乎有这样的重载。
【参考方案1】:
您可以使用匹配结果的.prefix()
获取字符串中不匹配的前缀部分,使用.suffix()
获取字符串其余部分的不匹配。
Demo(改编自here)。
【讨论】:
【参考方案2】:我在这里写了一篇关于这个主题的博文:http://blog.brainstembreakfast.com/update/c++/2014/09/20/regex-replace-ext/
你要找的功能是
template< class Traits, class CharT,
class STraits, class SAlloc >
inline std::basic_string<CharT,STraits,SAlloc>
regex_replace_ext( const std::basic_string<CharT,STraits,SAlloc>& s,
const std::basic_regex<CharT,Traits>& re,
const typename std::common_type<std::function<std::basic_string<CharT,STraits,SAlloc>
(const unsigned, const std::basic_string<CharT,STraits,SAlloc> &)>>::type& fmt,
std::regex_constants::match_flag_type flags =
std::regex_constants::match_default)
std::vector<int> smatches-1;
if(re.mark_count() == 0)
smatches.push_back(0);
else
smatches.resize(1+re.mark_count());
std::iota(std::next(smatches.begin()), smatches.end(), 1); //-1, 1, 2, etc...
unsigned smatch_count = smatches.size();
unsigned count = 0;
std::regex_token_iterator
<typename std::basic_string<CharT,STraits,SAlloc>::const_iterator>
tbegin(s.begin(), s.end(), re, smatches, flags), tend;
std::basic_stringstream<CharT,STraits,SAlloc> ret_val;
std::for_each(tbegin, tend, [&count,&smatch_count,&ret_val,&fmt]
(const std::basic_string<CharT,STraits,SAlloc> & token)
if(token.size() != 0)
if(!count)
ret_val << token;
else
ret_val << fmt(count,token);
count = ++count % smatch_count;
);
return ret_val.str();
用法:
const std::string bss("Id_1 [Fill_0] Id_2 [Fill_1] Id_3 Id_4 Id_5.");
const std::regex re("(\\.*?\\)|(\\[.*?\\])");
using dictionary = std::map<std::string,std::string>;
const std::vector<const dictionary> dict
"Id_1","This",
"Id_2","test",
"Id_3","my",
"Id_4","favorite",
"Id_5","hotdog"
,
"[Fill_0]","is a",
"[Fill_1]","of"
;
auto fmt1 = [&dict](const unsigned smatch, const std::string & s)->std::string
auto dict_smatch = smatch - 1;
if(dict_smatch > dict.size()-1)
return s; //more submatches than expected
const auto it = dict[dict_smatch].find(s);
return it != dict[dict_smatch].cend() ? it->second : s;
;
std::string modified_string = regex_replace_ext(bss, re, fmt1);
【讨论】:
以上是关于`re.sub(pattern, functor, string)` 用于 C++的主要内容,如果未能解决你的问题,请参考以下文章