std::regex 在文件路径中转义反斜杠

Nic*_*aus 5 c++ regex string c++11

我正在创建一个std::regex(__FILE__)作为单元测试的一部分的字符串,它检查一些打印文件名的异常输出。

在 Windows 上它失败了:

regex_error(error_escape):表达式包含无效的转义字符或尾随转义符。

因为__FILE__宏扩展包含未转义的反斜杠。

有没有比循环遍历结果字符串(即使用std算法或某些std::string函数)更优雅的方法来转义反斜杠?

Adr*_*thy 5

文件路径可以包含许多在正则表达式模式中具有特殊含义的字符。在一般情况下,仅转义反斜杠不足以进行稳健检查。

即使是简单的路径,例如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, "\\$&");
}
Run Code Online (Sandbox Code Playgroud)

(文件路径不能包含*or ?,但我已包含它们以保持函数的通用性。)

如果您不遵守“无原始循环”准则,则可能更快的实现将避免使用正则表达式:

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;
}
Run Code Online (Sandbox Code Playgroud)

尽管循环增加了一些混乱,但这种方法允许我们降低 的定义的转义级别metacharacters,这比正则表达式版本的可读性更好。