Подтвердить что ты не робот

Условно замените регулярные выражения в строке

Я пытаюсь заменить некоторые шаблоны в строке различными тестовыми патчами.

Пример:

string test = "test replacing \"these characters\"";

То, что я хочу сделать, - это заменить все '' на '_' и все другие символы, отличные от буквы или цифры, на пустую строку. У меня создано следующее регулярное выражение, и он, похоже, правильно маркер, но я не уверен, как (если возможно) выполнить замену условного кода с помощью regex_replace.

string test = "test replacing \"these characters\"";
regex reg("(\\s+)|(\\W+)");

ожидаемый результат после замены:

string result = "test_replacing_these_characters";

EDIT: Я не могу использовать boost, поэтому я оставил его вне тегов. Поэтому, пожалуйста, не отвечайте, включая повышение. Я должен сделать это со стандартной библиотекой. Возможно, что другое регулярное выражение достигло цели или что я просто застрял, выполняя два прохода.

EDIT2: Я не помню, какие символы были включены в \w во время моего исходного регулярного выражения, после того как я просмотрел его, я еще больше упростил выражение. Опять же, целью является любое соответствие \s +, которое должно быть заменено на "_", и все, что соответствует \W +, должно быть заменено пустой строкой.

4b9b3361

Ответ 1

Регулярные выражения С++ (0x, 11, tr1) не работают (stackoverflow) в каждом случае (посмотрите фраза регулярное выражение на этой странице для gcc), поэтому лучше использовать boost некоторое время.

Вы можете попробовать, если ваш компилятор поддерживает регулярные выражения:

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

using namespace std;

int main(int argc, char * argv[]) {
    string test = "test replacing \"these characters\"";
    regex reg("[^\\w]+");
    test = regex_replace(test, reg, "_");
    cout << test << endl;
}

Вышеописанное работает в Visual Studio 2012Rc.

Изменить 1. Чтобы заменить на две разные строки за один проход (в зависимости от соответствия), я думаю, что здесь это не сработает. В Perl это можно легко сделать в рамках оцененных замещающих выражений (/e switch).

Поэтому вам понадобятся два прохода, как вы уже подозревали:

 ...
 string test = "test replacing \"these characters\"";
 test = regex_replace(test, regex("\\s+"), "_");
 test = regex_replace(test, regex("\\W+"), "");
 ...

Изменить 2:

Если можно было бы использовать функцию обратного вызова tr() в regex_replace, тогда вы могли бы изменить подстановку там, например:

 string output = regex_replace(test, regex("\\s+|\\W+"), tr);

с tr() выполняет замещающую работу:

 string tr(const smatch &m) { return m[0].str()[0] == ' ' ? "_" : ""; }

проблема была бы решена. К сожалению, не существует такой перегрузки в некоторых реализациях регулярных выражений С++ 11, но Boost имеет один. Следующее будет работать с повышением и использованием одного прохода:

...
#include <boost/regex.hpp>
using namespace boost;
...
string tr(const smatch &m) { return m[0].str()[0] == ' ' ? "_" : ""; }
...

string test = "test replacing \"these characters\"";
test = regex_replace(test, regex("\\s+|\\W+"), tr);   // <= works in Boost
...

Может быть, когда-нибудь это сработает с С++ 11 или другим номером.

Привет

БВУ