C ++中的正则表达式不适用于方形括号

时间:2014-01-18 16:49:52

标签: c++ regex

我正在尝试编写正则表达式来验证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;

当使用第一个正则表达式(“&lt; [^ /] *?&gt;”)时,我得到:

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

当使用第二个正则表达式(“&lt; [a-z] *&gt;”)时,我得到:

0
openCap: 

当使用第三个正则表达式(“&lt;。*&gt;”)时,我得到:

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) 

3 个答案:

答案 0 :(得分:2)

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

现在,让我们假装用RegExes解析XML不会有问题:你提供的所有RegExes都应该匹配regex reg("<[^/]*>"); if (regex_match("<test>", reg)) cout << "Matched..." << endl; else cout << "Didn't match..." << endl; 并在我尝试的实现中这样做,这表明你的错误您使用的代码或库,但我没有在您的代码中看到一个,并且正则表达式的标准实现也不应该是错误的...

编辑:我刚刚尝试使用C ++,RegExes也可以使用。在极简主义的实施中

<[a-z]*>

产生输出“匹配...” - 并且{{1}}也可以。我在这个过期时使用过clang-500.2.79。这基本上证实了编译器提供的实现是错误的。

答案 1 :(得分:0)

你试过的正则表达式

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

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

.*表示任何字符(0次或更多次)                            (匹配尽可能多的数量))

答案 2 :(得分:0)

我遇到了同样的问题。看起来字符集匹配(带方括号)在gcc4.x中使用默认的ECMA脚本语法。使用std :: regex:扩展解析器似乎工作。 即

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