簡體   English   中英

文件路徑中的std :: regex轉義反斜杠

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM