使用扩展 POSIX 语法的 C 正则表达式与 C++ 正则表达式中的不同行为

问题描述

在使用 C POSIX 正则表达式库和 C++ 标准库实现时,我看到了不同的结果。这是我的代码

string pattern = "\\s";
string testString = " ";

regex_t cre;
int status = regcomp(&cre,pattern.c_str(),REG_EXTENDED);
int result = (regexec(&cre,testString.c_str(),0) == 0);
cout << "C: " << result << endl;

regex re(pattern,regex_constants::extended);
smatch sm;
cout << "C++: " << regex_search(testString,sm,re) << endl;

C 部分成功匹配空格,但 C++ 部分抛出此错误

terminate called after throwing an instance of 'std::regex_error'
  what():  Unexpected escape character.

我知道字符串文字被转义意味着模式匹配中使用的实际正则表达式应该是\s。我也只在使用 POSIX 扩展语法时看到这个问题。在C++版本中,如果我在构造正则表达式时不指定POSIX扩展语法,则认为ECMAScript语法,可以正确解析。

这里发生了什么?

解决方法

regex_constants::extended 触发不支持 POSIX ERE regex syntaxshorthand character classes。请注意,C regex.h 模块支持 \s 作为非标准扩展。

要匹配启用了 regex_constants::extended 的 POSIX ERE 风格中的任何空格,您需要使用 string pattern = "[[:space:]]"

但是,您应该只依赖于 default ECMAScript flavor,并使用

regex re(pattern);
// or
regex re(pattern,std::regex::ECMAScript);
,

在 Posix RE 中

任何以转义开头的普通字符的效果是不确定的。

(来自boost docs

9.4.2 ERE 普通字符

普通字符是与自身匹配的 ERE。普通字符是受支持字符集中的任何字符,但 ERE 特殊字符中列出的 ERE 特殊字符除外。以未转义 ( '\' ) 开头的普通字符的解释未定义,除非在括号表达式的上下文中(请参阅 ERE 括号表达式)。

(来自posix docs

类似的措辞适用于 BRE。

因此两者都符合 posix,因为您的 RE 实际上未定义。