C++:在macOS(而非Linux)上具有负前瞻和^匹配的正则表达式

lx0bsm1f  于 2022-12-15  发布在  Mac
关注(0)|答案(1)|浏览(120)

为什么在macOS(和Windows)上,而不是Linux上,同样的带有负前瞻的正则表达式会报告匹配?
下面是C++中的示例代码:

#include <iostream>
#include <regex>

int main() {
  std::regex rx("^(((?!(\\/|^)\\.).)*?)$");
  std::string input = "foo.bar";

  std::cout << std::regex_match(input, rx) << std::endl;
}

在macOS和Windows上的结果:1
Linux上的结果(尝试使用GCC 11):0
此问题似乎源于负前瞻?!(\\/|^)。具体而言,删除|^可解决此问题,因此它与^的负前瞻相关。
尝试使用std::regex_match(input, rx, std::regex_constants::match_not_bol),但运气不佳。
有趣的是,当目标字符串不包含.时,结果仍然相同。
最后,在JavaScript中运行的同一正则表达式在所有平台上都匹配。
有关所用编译器版本的一些详细信息:

  • macOS操作系统:Apple clang version 14.0.0 (clang-1400.0.29.202)
  • Linux系统:g++-11 (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0
  • 窗口:Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x86
cgh8pdjw

cgh8pdjw1#

不同的操作系统使用不同的正则表达式引擎。
POSIX C (C)行参见https://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines
C++标准库提供了一个基于POSIX扩展正则表达式(ERE)语法的正则表达式引擎参考:-POSIX Extended Regular Expression Syntax
^-字符在正则表达式中用于匹配字符串的开头,但在ERE语法中,它在组内使用时也有特殊含义。在ERE语法中,组内的^字符否定其后面的字符类,因此在本例中,组内的^字符(/|^)对字符类求反。这会导致正则表达式引擎匹配任何非.的字符,这就是目标字符串包含.字符时行为不同的原因。
您需要删除^字符:
std::regex rx("^(((?!(\\/|^)).)*?)$");

相关问题