我创建一个std::regex(__FILE__)
字符串作为单元测试的一部分,它检查一些打印文件名的异常输出。
在Windows上,它失败了:
regex_error(error_escape):表达式包含无效的转义字符或尾随转义。
因为__FILE__
宏扩展包含未转义的反斜杠。
是否有更优雅的方法来逃避反斜杠而不是循环生成的字符串(即使用std
算法或某些std::string
函数)?
答案 0 :(得分:1)
最后,我转到@AdrianMcCarthy的more robust approach。
这是我解决问题的不雅方法,万一有人偶然发现这个问题,实际上是在寻找解决方法:
std::string escapeBackslashes(const std::string& s)
{
std::string out;
for (auto c : s)
{
out += c;
if (c == '\\')
out += c;
}
return out;
}
然后
std::regex(escapeBackslashes(__FILE__));
这是O(N)
,这可能和你在这里做的一样好,但涉及很多字符串复制,我认为这并不是绝对必要的。
答案 1 :(得分:1)
以下是polymapper
。
它需要一个带有元素的操作并返回一个范围,"映射操作"。
它生成一个接收容器的函数对象,并应用"映射操作"每个元素。它返回与容器相同的类型,其中每个元素都通过" map操作"进行扩展/收缩。
template<class Op>
auto polymapper( Op&& op ) {
return [op=std::forward<Op>(op)](auto&& r) {
using std::begin;
using R=std::decay_t<decltype(r)>;
using iterator = decltype( begin(r) );
using T = typename std::iterator_traits<iterator>::value_type;
std::vector<T> data;
for (auto&& e:decltype(r)(r)) {
for (auto&& out:op(e)) {
data.push_back(out);
}
}
return R{ data.begin(), data.end() };
};
}
以下是escape_stuff
:
auto escape_stuff = polymapper([](char c)->std::vector<char> {
if (c != '\\') return {c};
else return {c,c};
});
int main() {
std::cout << escape_stuff(std::string(__FILE__)) << "\n";
}
这种方法的优点是可以解决弄乱容器内脏的问题。你编写的代码与字符或元素混淆,整体逻辑不是你的问题。
缺点是polymapper有点奇怪,并且完成了不必要的内存分配。 (这些可以优化,但这会使代码更复杂)。
答案 2 :(得分:1)
文件路径可以包含许多在正则表达式模式中具有特殊含义的字符。在一般情况下,仅仅反转反斜杠不足以进行强大的检查。
即使是简单的路径,如C:\Program Files (x86)\Vendor\Product\app.exe
,也包含几个特殊字符。如果要将其转换为正则表达式(或正则表达式的一部分),则不仅需要转义反斜杠,还要转义括号和句点(点)。
幸运的是,我们可以使用更正则的表达式解决正则表达式问题:
std::string EscapeForRegularExpression(const std::string &s) {
static const std::regex metacharacters(R"([\.\^\$\-\+\(\)\[\]\{\}\|\?\*)");
return std::regex_replace(s, metacharacters, "\\$&");
}
(文件路径不能包含*
或?
,但我已将它们包含在内以保持此功能的通用性。)
如果你不遵守&#34;没有原始循环&#34;准则,一个可能更快的实现将避免正则表达式:
std::string EscapeForRegularExpression(const std::string &s) {
static const char metacharacters[] = R"(\.^$-+()[]{}|?*)";
std::string out;
out.reserve(s.size());
for (auto ch : s) {
if (std::strchr(metacharacters, ch))
out.push_back('\\');
out.push_back(ch);
}
return out;
}
尽管循环增加了一些混乱,但这种方法允许我们在metacharacters
的定义上放弃一个转义级别,这是对正则表达式版本的可读性胜利。