[英]std::regex escape backslashes in file path
我是一個字符串,用於創建std::regex(__FILE__)
作為單元測試的一部分,該單元測試將檢查打印文件名的某些異常輸出。
在Windows上,它失敗並顯示:
regex_error(error_escape):表達式包含無效的轉義字符或尾隨轉義符。
因為__FILE__
宏擴展包含未轉義的反斜杠。
有沒有比循環遍歷結果字符串(即使用std
算法或某些std::string
函數)更優雅的方式來轉義反斜杠?
最后,我切換到@AdrianMcCarthy的更強大的方法 。
如果有人偶然發現這種實際的解決方法,這是解決問題的一種優雅方法:
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)
可能和您在此處所做的一樣好,但是涉及很多字符串復制,我想這並不是嚴格必要的。
這是polymapper
。
它接受一個操作,該操作接受和元素,並返回一個范圍,即“映射操作”。
它產生一個帶容器的功能對象,並將“映射操作”應用於每個元素。 它返回與容器相同的類型,其中每個元素都已通過“映射操作”擴展/收縮。
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有點奇怪,並且完成了不必要的內存分配。 (可以優化這些代碼,但這會使代碼更復雜)。
文件路徑可以包含許多在正則表達式模式中具有特殊含義的字符。 通常情況下,僅轉義反斜杠不足以進行強大的檢查。
即使是簡單的路徑,例如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, "\\$&");
}
(文件路徑不能包含*
或?
,但是為了使該函數具有通用性,我將它們包括在內。)
如果您不遵守“沒有原始循環”指南,那么可能更快的實現將避免使用正則表達式:
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
的定義進行某種程度的轉義,這是對正則表達式版本的可讀性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.