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

Как избежать строки для использования в Boost Regex

Я просто обнимаю регулярные выражения, и я использую библиотеку Regex Boost.

Мне нужно использовать регулярное выражение, которое содержит определенный URL-адрес, и оно задыхается, потому что очевидно, что в URL-адресе зарезервированы символы, которые зарезервированы для регулярного выражения и должны быть экранированы.

Есть ли какая-либо функция или метод в библиотеке Boost, чтобы избежать строки для такого использования? Я знаю, что есть такие методы в большинстве других реализаций регулярных выражений, но я не вижу их в Boost.

Альтернативно, есть ли список всех символов, которые нужно было бы экранировать?

4b9b3361

Ответ 1

. ^ $ | ( ) [ ] { } * + ? \

По иронии судьбы, вы можете использовать регулярное выражение, чтобы избежать URL-адреса, чтобы его можно было вставить в регулярное выражение.

const boost::regex esc("[.^$|()\\[\\]{}*+?\\\\]");
const std::string rep("\\\\&");
std::string result = regex_replace(url_to_escape, esc, rep,
                                   boost::match_default | boost::format_sed);

(Флаг boost::format_sed указывает на использование заменяющего строкового формата sed. В sed escape & выводит все, что соответствует по всему выражению)

Или, если вам не нравится формат строковой замены sed, просто измените флаг на boost::format_perl, и вы можете использовать знакомый $& для обозначения того, что соответствует всему выражению.

const std::string rep("\\\\$&");
std::string result = regex_replace(url_to_escape, esc, rep,
                                   boost::match_default | boost::format_perl);

Ответ 2

Используя код из Dav (+ a fix from comments), я создал функцию ASCII/Unicode regex_escape():

std::wstring regex_escape(const std::wstring& string_to_escape) {
    static const boost::wregex re_boostRegexEscape( _T("[.^$|()\\[\\]{}*+?\\\\]") );
    const std::wstring rep( _T("\\\\&") );
    std::wstring result = regex_replace(string_to_escape, re_boostRegexEscape, rep, boost::match_default | boost::format_sed);
    return result;
}

Для версии ASCII используйте std::string/boost::regex вместо std::wstring/boost::wregex.

Ответ 3

То же самое с boost::xpressive:

const boost::xpressive::sregex re_escape_text = boost::xpressive::sregex::compile("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\\\])");

std::string regex_escape(std::string text){
    text = boost::xpressive::regex_replace( text, re_escape_text, std::string("\\$1") );
    return text;
}

Ответ 4

В С++ 11 вы можете использовать необработанные строковые литералы, чтобы избежать escape-строки:

std::string myRegex = R"(something\.com)";

См. http://en.cppreference.com/w/cpp/language/string_literal, пункт (6).