我需要将以下行与多个捕获组匹配:
0.625846 29Si 29 [4934.39 0] [0.84 100000000000000.0]
我使用正则表达式:
^(0+.[0-9]?e?[+-]?[0-9]+)s+([0-9]+.?[0-9]*|[0-9][0-9]?[0-9]?[A-Z][a-z]?)s+([0-9][0-9]?[0-9]?)s+([.*])s+([.*])$
有关regex101工作区,请参阅此链接。然而,我发现当我使用regex.h
尝试匹配时,它在OSX或linux上的表现不同,特别是:
失败时间:OSX:10.14.6LLVM:10.0.1(clang-1001.0.46.4(
工作范围:linux:Ubuntu 18.04g++:7.5.0
我编写了一个简短的代码来重现这个问题,用g++ regex.cpp -o regex
:编译
#include <iostream>
//regex
#include <regex.h>
using namespace std;
int main(int argc, char** argv) {
//define a buffer for keeping results of regex matching
char buffer[100];
//regex object to use
regex_t regex;
//*****regex match and input file line*******
string iline = "0.625846 29Si 29 [4934.39 0] [0.84 100000000000000.0]";
string matchfile="^(0+\.[0-9]?e?[+-]?[0-9]+)\s+([0-9]+\.?[0-9]*|[0-9][0-9]?[0-9]?[A-Z][a-z]?)\s+([0-9][0-9]?[0-9]?)\s+(\[.*\])\s+(\[.*\])$";
//compile the regex
int reti = regcomp(®ex,matchfile.c_str(),REG_EXTENDED);
regerror(reti, ®ex, buffer, 100);
if(reti==0)
printf("regex compile success!n");
else
printf("regcomp() failed with '%s'n", buffer);
//match the input line
regmatch_t input_matchptr[6];
reti = regexec(®ex,iline.c_str(),6,input_matchptr,0);
regerror(reti, ®ex, buffer, 100);
if(reti==0)
printf("regex compile success!n");
else
printf("regexec() failed with '%s'n", buffer);
//******************************************
return 0;
我还修改了我的正则表达式以符合POSIX(我想是?(,根据这篇文章,我删除了以前使用的+?
和*?
运算符,但可能遗漏了一些使我与POSIX不兼容的内容?然而,regex现在似乎编译正确,这让我觉得我使用了一个有效的regex,但我仍然不明白为什么没有获得匹配。我理解LLVM的要求。
如何修改正则表达式以正确匹配?
要回答直接的问题,您需要使用
string matchfile="^(0+\.[0-9]?e?[+-]?[0-9]+)[[:space:]]+([0-9]+\.?[0-9]*|[0-9][0-9]?[0-9]?[A-Z][a-z]?)[[:space:]]+([0-9][0-9]?[0-9]?)[[:space:]]+(\[.*\])[[:space:]]+(\[.*\])$";
也就是说,您可以在括号表达式中使用[:space:]
POSIX字符类,而不是像s
那样使用Perl。
您提到您在括号表达式之外尝试了[:space:]
,但它不起作用——这是意料之中的事。根据字符类,
[:digit:]
是一个POSIX字符类,在类似[x-z[:digit:]]
的括号表达式中使用。
这意味着POSIX字符类只有在括号表达式中使用时才被解析为这样。