Как избежать строки для использования в Boost Regex - PullRequest
27 голосов
/ 10 августа 2009

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

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

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

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

Ответы [ 4 ]

38 голосов
/ 10 августа 2009
. ^ $ | ( ) [ ] { } * + ? \

Как ни странно, вы можете использовать регулярное выражение для экранирования своего 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 экранирование & выведет все, что соответствует целому выражению)

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

const std::string rep("\\\\$&");
std::string result = regex_replace(url_to_escape, esc, rep,
                                   boost::match_default | boost::format_perl);
13 голосов
/ 15 ноября 2009

Используя код из Dav (+ исправление из комментариев), я создал функцию 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.

4 голосов
/ 11 ноября 2009

То же самое с 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;
}
2 голосов
/ 20 июня 2017

В C ++ 11 вы можете использовать необработанные строковые литералы , чтобы избежать экранирования строки регулярного выражения:

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

См. http://en.cppreference.com/w/cpp/language/string_literal,позиция (6).

...