regex_search и regex_replace с Boost - PullRequest
0 голосов
/ 15 марта 2011

Я пытаюсь выполнить цикл между некоторыми строками, разделенными парой '$' в строке, заменяя каждое совпадение определенным значением, чтобы получить строку вывода со всеми замененными маркерами, но я застрял во втором совпадении поскольку я не знаю, как объединить новое значение замены:

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 голосов
/ 16 марта 2011

Хотя я не уверен на 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 );

Надеюсь, это поможет

0 голосов
/ 16 марта 2011

Поскольку вы запрашиваете только первое значение в строке, подлежащей замене (с помощью boost :: format_first_only flag), исходная строка

"Mr $SURNAME$ from $LOCATION$"

будет преобразована в

"Mr ACTUAL_VAL from $LOCATION$"

на первой итерации, а затем

" from ACTUAL_VAL"

будет добавлено к ней, так как вы явно задаете начала begin "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, то вы должны сделать «начало» и «конец»отметить начало и конец скользящего окна, которое содержит ровно один шаблон.

...