问题
I'm trying to loop among some strings delimited by a '$' pair in a line, replacing each match with a specific value in order to get an output line with all markers replaced but I'm stuck at the second match as I don't know how to concatenate the new replacement value:
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;
}
The problem is in the outLine.append( t.str() ) as the concatenation is not done properly because after the first match, the outLine holds already some of the characters preceding the next match.
回答1:
Though I'm not 100% sure about your intent, I presume your goal is replacing
each matched substring in fileLine
with the corresponding value of valuesMap
.
If so, the following code might meet your purpose:
...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 );
Hope this helps
回答2:
Since you request only first value in a string to be replaced (by using boost::format_first_only flag) original string
"Mr $SURNAME$ from $LOCATION$"
will be converted into
"Mr ACTUAL_VAL from $LOCATION$"
on first iteration and then
" from ACTUAL_VAL"
will be appended to it since you explicitly set begin to "what[0].second. so final output is
"Mr ACTUAL_VAL from $LOCATION$ from ACTUAL_VAL"
which is not what you need. Here is working example that has side effect - it modifies 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;
If you don't want to modify fileLine, then you should make "begin" and "end" to mark the beginning and end of sliding window that contains exactly one pattern.
来源:https://stackoverflow.com/questions/5315558/regex-search-and-regex-replace-with-boost