Как избежать строки для использования в Boost Regex
Я просто обнимаю регулярные выражения, и я использую библиотеку Regex Boost.
Мне нужно использовать регулярное выражение, которое содержит определенный URL-адрес, и оно задыхается, потому что очевидно, что в URL-адресе зарезервированы символы, которые зарезервированы для регулярного выражения и должны быть экранированы.
Есть ли какая-либо функция или метод в библиотеке Boost, чтобы избежать строки для такого использования? Я знаю, что есть такие методы в большинстве других реализаций регулярных выражений, но я не вижу их в Boost.
Альтернативно, есть ли список всех символов, которые нужно было бы экранировать?
Ответы
Ответ 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).