正则表达式C++不使用方括号

Regex in C++ Not Working with Square Brackets

本文关键字:方括号 C++ 正则表达式      更新时间:2023-10-16

我正在尝试编写正则表达式来验证XML文件并提取存储在C++标签之间的字符串。

这是我的目标正则表达式之一:

"<[^/]*?>"

但是,这不起作用。也没有像这样简单的事情:

"<[a-z]*>"

但是,这将产生匹配项:

"<.*>"

括号似乎无法匹配。

以下是我正在使用的代码的相关部分:

string testString = "<test>";
regex xmlRegOpenTag("<[^/]*?>", regex_constants::extended); 
smatch smOpen;
cout << regex_match(testString, smOpen, xmlRegOpenTag) << endl;
string openCap = smOpen[0];
cout << "openCap: " << openCap << endl;

我尝试过使用其他标志,如regex_constants::basic等。似乎没有任何效果。我正在使用 gcc 版本 4.7.3 进行编译。

对于那些提到我不应该使用正则表达式解析XML的人:我只需要解析我自己创建的XML文件,所以这不是问题。

我使用的是 C++11 标准。在我的头文件中,我包含正则表达式:

#include <regex>
using namespace std;

当使用第一个正则表达式("<[^/]*?>")时,我得到:

terminate called after throwing an instance of 'std::regex_error'
what():  regex_error
Abort

使用第二个正则表达式("<[a-z]*>")时,我得到:

0
openCap: 

当使用第三个正则表达式("<.*>")时,我得到:

1
openCap: <test>

这是我可以提供的有关我正在使用的编译器的信息:

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.7.3-1ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --enable-objc-gc --with-cloog --enable-cloog-backend=ppl --disable-cloog-version-check --disable-ppl-version-check --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1) 

首先,XML不是一种常规语言,你不应该尝试使用RegExes来解析它,最终它会给你带来一些真正的头疼,你应该使用XML的可用解析器之一。例如,假设您有诸如"<foo><bar /></foo>"之类的东西,例如<.*>将匹配整个字符串,而不仅仅是第一个标签,而是整个字符串。您可以尝试将"lazy"匹配与<.*?>一起使用,这会尝试匹配尽可能少的字符,但例如,如果您在属性中的字符串中有>,则仍可能会中断。

现在,让我们假装使用正则表达式解析 XML 不会有问题:您提供的所有正则表达式都应该<test>匹配并在我尝试的实现中这样做,这表明您的代码或您使用的库中存在错误,但我在您的代码中没有看到一个错误,正则表达式的标准实现也不应该有问题......

编辑:我刚刚尝试了C++,正则表达式也可以工作。在极简主义实现中

regex reg("<[^/]*>");
if (regex_match("<test>", reg))
cout << "Matched..." << endl;
else
cout << "Didn't match..." << endl;

生成输出"匹配..."-<[a-z]*>也可以工作。我在此过期中使用了 clang-500.2.79。这基本上确认了编译器提供的实现是错误的。

您尝试过的
正则表达式

[^/]*表示除以下字符之外的任何字符:'/'(0 次或更多次(匹配尽可能多的数量))

[a-z]*表示以下任何字符:'a''z'(0 或更多) 次数(尽可能匹配最大数量))

.*指示任何字符(0 次或更多次) (尽可能匹配金额))

我遇到了同样的问题。在 gcc4.x 中,字符集匹配(带方括号)似乎使用默认的 ECMA 脚本语法被破坏。使用 std::regex:extended 解析器似乎有效。 即

std::regex re(".*", std::regex::ECMAScript); -> ok
std::regex re("[a-z]", std::regex::ECMAScript); -> regex_error
std::regex re("[a-z]", std::regex::extended); -> ok