带有Boost的regex_search和regex_replace

时间:2011-03-15 17:26:58

标签: c++ boost-regex

我正在尝试在一行中用'$'对分隔的一些字符串中循环,用一个特定的值替换每个匹配,以便获得一个输出行,所有标记都被替换但是我被困在第二个匹配因为我不知道如何连接新的替换值:

const boost::regex expression( "\\$[\\w]+\\$" );
string fileLine( "Mr $SURNAME$ from $LOCATION$" );
string outLine;

string::const_iterator begin = fileLine.begin();
string::const_iterator end = fileLine.end();

boost::match_results<string::const_iterator> what;
boost::match_flag_type flags = boost::match_default;

while ( regex_search( begin, end, what, expression, flags ) ) {
  actualValue = valuesMap[what[0]];

  ostringstream t( ios::out | ios::binary );
  ostream_iterator<char, char> oi( t );

  boost::regex_replace( oi, begin, end, expression, actualValue, 
                        boost::match_default | boost::format_first_only );
  outLine.append( t.str() );
  begin = what[0].second;
}

问题出在outLine.append(t.str())中,因为连接没有正确完成,因为在第一次匹配之后,outLine已经保存了下一个匹配之前的一些字符。

2 个答案:

答案 0 :(得分:0)

由于您只请求要替换的字符串中的第一个值(通过使用 boost :: format_first_only 标志)原始字符串

"Mr $SURNAME$ from $LOCATION$"

将转换为

"Mr ACTUAL_VAL from $LOCATION$"

在第一次迭代然后

" from ACTUAL_VAL"

将附加到它,因为您明确设置开始“what [0] .second。 所以最后的输出是

"Mr ACTUAL_VAL from $LOCATION$ from ACTUAL_VAL"

这不是你需要的。 这是一个有副作用的工作示例 - 它修改了fileLine:

   const boost::regex expression( "\\$[\\w]+\\$" );
    string fileLine( "Mr $SURNAME$ from $LOCATION$" );
    string outLine;

    string::const_iterator begin = fileLine.begin();
    string::const_iterator end = fileLine.end();

    boost::match_results<string::const_iterator> what;
    boost::match_flag_type flags = boost::match_default;

    while ( regex_search( begin, end, what, expression, flags ) ) 
    {
        const char* actualValue = valuesMap[what[0]];

        ostringstream t( ios::out | ios::binary );
        ostream_iterator<char, char> oi( t );

        boost::regex_replace( oi, begin, end, expression, 
`enter code here`actualValue, boost::match_default | boost::format_first_only );

        fileLine.assign(t.str());
        begin = fileLine.begin();
        end = fileLine.end();        
    }

    std::cout << fileLine << std::endl;

如果您不想修改fileLine,那么您应该使用“begin”和“end”来标记包含一个模式的滑动窗口的开头和结尾。

答案 1 :(得分:0)

虽然我对你的意图并不是100%肯定,但我认为你的目标正在取代 fileLine中每个匹配的子字符串,其对应值为valuesMap 如果是这样,以下代码可能符合您的目的:

  ...same as your code...

  while ( regex_search( begin, end, what, expression, flags ) ) {
    outLine.insert( outLine.end(), begin, what[0].first );
    outLine += valuesMap[what[0]];
    begin = what[0].second;
  }

  outLine.insert( outLine.end(), begin, end );

希望这有帮助