如何在c ++ 11 std :: regex_replace中检查是否成功?

时间:2016-03-05 17:19:27

标签: c++ regex c++11

我想做一个与perl检查替换操作相当的c ++ 11:

sharedInstance

我可以毫无困难地进行更换:

my $v = "foo.rat"

if ( $v =~ s/\.rat$/.csv/ )
{
   ...
}

这给出了:

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

int main()
{
   std::string s{ "foo.rat" } ;
   std::regex reg{ R"((.*)\.rat$)" } ;

   s = std::regex_replace( s, reg, "$1.csv" ) ;

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

   s = std::regex_replace( "foo.noo", reg, "$1.csv" ) ;
   std::cout << s << std::endl ;

   return 0 ;
}

请注意,对非匹配表达式的替换操作不会抛出错误(这正是我所期望的)。

查看regex_replace文档,对我来说,如何检查替换操作是否成功并不明显。我可以做一个字符串比较,但这似乎倒退了?

4 个答案:

答案 0 :(得分:1)

只需将accepted answer添加到std::regex_iterator中即可。当可能发生多次更换时,这可能很方便。

迭代器std::regex_iterator重复调用std::regex_search(),直到找到所有匹配项。如果迭代器的开头位置和结尾位置相同,则找不到匹配项。

函数bool regex_replace(std::string &str, const std::string &re, const std::string& replacement)实现了以下行为:

#include <iostream>
#include <regex>

bool regex_replace(std::string &str, const std::string &re, const std::string& replacement) {
    std::regex regexp(re);

    //Search regex
    std::sregex_iterator begin = std::sregex_iterator(str.begin(), str.end(), regexp);
    std::sregex_iterator end = std::sregex_iterator();

    //replace using iterator
    for (std::sregex_iterator i = begin; i != end; ++i)
        str.replace(i->position(), i->length(), replacement);

    //returns true if at least one match was found and replaced
    return (begin != end);
}

此功能在原地运行。最后str有替换项。仅当进行任何替换时,该函数才会返回true。

以下代码显示了如何使用它进行多次替换并检测是否进行了替换:

int main(int argc, char** argv) {    
    std::string rgx("[0-9]");
    std::string str("0a1b2c3d4e5");
    std::string replacement("?");

    bool found = regex_replace(str, rgx, replacement);
    std::cout << "Found any: " << (found ? "true" : "false") << std::endl;
    std::cout << "string:    " << str << std::endl;
    return 0;
}

代码用引号'?'代替每个数字:

Found any:  true
string:     ?a?b?c?d?e?

答案 1 :(得分:0)

尝试找到与std::regex_matchstd::regex_search的匹配项,检查某些内容是否匹配,然后使用std::string::replace替换找到的字符串部分。这不应该导致性能下降。

答案 2 :(得分:0)

使用 std::regex_constants::format_no_copy 标志来改变 regex_replace() 的行为。看看下面的代码。

如果匹配失败,返回字符串现在将为空。

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

int main()
{
   std::string s{ "foo.rat" } ;
   std::regex reg{ R"((.*)\.rat$)" } ;
   auto rxMatchFlag = std::regex_constants::format_no_copy;  //<---use this to modify the behavior of regex_replace when matching failed.

   s = std::regex_replace( s, reg, "$1.csv", rxMatchFlag) ;
    
   if(!s.empty()) std::cout << s << std::endl ;
   else std::cout << "failed match" << std::endl;

   s = std::regex_replace( "foo.noo", reg, "$1.csv", rxMatchFlag) ; 
   if(!s.empty()) std::cout << s << std::endl ;
   else std::cout << "failed match" << std::endl;

   return 0 ;
}

对于其他标志,查看它们 here

答案 3 :(得分:-1)

我不相信有任何直接的方法来确定是否有任何更换。

(不要将此与“成功/不成功”混淆,这不是完全相同的事情。)