为什么在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
1条答案
按热度按时间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("^(((?!(\\/|^)).)*?)$");