首页 > 解决方案 > C++ 正则表达式失败,而在线检查器工作

问题描述

我有这个代码:

class Clazz {
private:
  constexpr char _csVersionPattern[] = "^[^\\(\\[\\)\\],]+$";
  //constexpr char _csVersionPattern[] = "(^([\\(\\[])[!-'\\*+\\.-Z\\\\^-z\\|~-]*,[!-'\\*+\\.-Z\\\\^-z\\|~-]*([\\)\\]])$)|(^[^\\(\\[\\)\\],]+$)";
  constexpr char _csIdPattern[] = "^[!-~]+$";
public:
  void func(std::string const& aId, std::string const& aVersion) {
    std::regex idRegex{ _csIdPattern, std::regex::extended };
    std::regex versionRegex{ _csVersionPattern, std::regex::extended };
    auto validId = std::regex_match(aId, idRegex);
    auto validVersion = std::regex_match(aVersion, versionRegex);
    _valid = (validId && validVersion);
  }
};

当我将其称为object.func("id", "version");validId 时,validId 为 true,validVersion 为 false。如果我在评论中采用更复杂的模式,它也会失败。这发生在 Visual Studio 2019 以及最近的 g++ 和 clang++ 中。但是,当我在这里尝试相同的版本模式时: ^[^\(\[\)\],]+$ 它匹配字符串“版本”。复杂的变体也有效。这些模式在 std::regex 构造函数中编译(没有例外)。我做错了什么?

提前致谢。

编辑: 是在Godbolt上。原来是 C++14,这里是 C++17,都失败了。

标签: c++regex

解决方案


您编写的正则表达式与 ECMAScript 兼容,但您选择了std::regex::extended风格,即POSIX ERE

在 POSIX ERE 模式中,您不能使用正则表达式转义序列。例如,您不能将\]括号表达式放在括号内并期望它与文字匹配]。事实上,它会提前关闭括号表达式。正^[^\(\[\)\],]+$则表达式必须写为^[^][(),]+$括号]表达式开头的 被视为文字]字符(这称为智能放置,顺便说一句,-必须在括号表达式的末尾使用)。

不过,这里最简单的解决方法是删除该std::regex::extended选项并使用默认的 ECMAScript 选项:

std::regex idRegex{ _csIdPattern };
std::regex versionRegex{ _csVersionPattern };

推荐阅读