2013-07-20 78 views
0

我不认为我明白如何只返回匹配的正则表达式。我有一个网页文件。我正在尝试获取页面中的所有链接。正则表达式工作正常。但是,如果我打印出来,它会打印出匹配发生的行。我只想显示比赛。我看到你可以做分组,所以我尝试了,并且为我的第二次printf调用返回一个int值。根据文件它是一个抵消。但抵消了什么?它看起来并不准确,要么是因为当该行的字符32与正则表达式无关时它会说32。我只是看到第一场比赛就退出了。我哪里错了?regmatch_t我怎样才能得到匹配?

char line[1000]; 
    FILE *fp_original; 
    fp_original = fopen (file_original_page, "r"); 

    regex_t re_links; 
    regmatch_t group[2]; 
    regcomp (&re_links, "(href|src)=[\"|'][^\"']*[\"|']", REG_EXTENDED); 

    while (fgets (line, sizeof line, fp_original) != NULL) { 
    if (regexec (&re_links, line, 2, group, 0) == 0) { 
     printf ("%s", line); 
     printf ("%u\n", line[group[1].rm_so]); 
     exit (1); 
    } 
    } 

    fclose (fp_original); 
+1

当我与一个匹配的输入运行程序,它打印'104',这是不是一个偏移,但*是*在发现该字符的偏移量! (这是匹配字符串的第一个字符的'href'的'h'的ASCII码。)你是否通过打印'line [group [i] .rm_so]'而不是'group [i] .rm_so'? –

+0

@ WumpusQ.Wumbley你说得对,'line [group [1] .rm_so]'确实返回ascii码。但是当我尝试使用'group [1] .rm_so'时,我得到一个警告:'警告:格式'%u'期望输入'unsigned int',但参数2的类型为'regoff_t''。任何想法为什么? – user983223

+0

我可以告诉你如何解决这个问题,但我想先解决其他问题。对用户来说没有意义的警告消息是一个问题。警告应该包含您需要的所有信息。从我的角度来看,它确实如此。我无法想象*不了解它。你有机会通过解释你的思维过程来帮助那些将来处于你的位置的人,现在,在混乱离开你之前,你成为我们中的一员... –

回答

3

regmatch_t阵列

regmatch_t是matcharray,你传递给正则表达式电话。如果我们传递2作为正则表达式中的匹配数,我们在regmatch_t [0]中获得整个匹配,并在regmatch_t [1]中获得子匹配。

例如:

size_t nmatch = 2; 
regmatch_t pmatch[2]; 

rc = regex(&re_links, line, nmatch, pmatch, 0); 

如果成功了,你可以得到的子表达式如下:

pmatch[1].rm_eo - pmatch[1].rm_so, &line[pmatch[1].rm_so], 
pmatch[1].rm_so, pmatch[1].rm_eo - 1); 

这里是如何应用上面的例子:

#include <regex.h>                
#include <stdio.h>                
#include <stdlib.h>                

int main(void)                 
{                     
    regex_t preg;                

    char *string = "I'm a link to somewhere";        
    char *pattern = ".*\\(link\\).*";          

    size_t  nmatch = 2;               
    regmatch_t pmatch[2];               


    regcomp(&preg, pattern, 0);             
    regexec(&preg, string, nmatch, pmatch, 0);          

    printf("a matched substring \"%.*s\" is found at position %d to %d.\n",  
    pmatch[1].rm_eo - pmatch[1].rm_so, &string[pmatch[1].rm_so], 
    pmatch[1].rm_so, pmatch[1].rm_eo - 1);         

    regfree(&preg);                

    return 0;                  
}  

以上代码肯定不会保存。它只是作为一个例子。如果你与你的团队交换pmatch,它应该工作。另外不要忘了加上括号,你想在你的小组捕捉到你的正则表达式的一部分 - >\\(.*\\)

编辑

为了避免编译器有关领域的精度,可以警告与此更换整个printf的一部分:

char *result; 

result = (char*)malloc(pmatch[1].rm_eo - pmatch[1].rm_so); 
strncpy(result, &string[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); 

printf("a matched substring \"%s\" is found at position %lld to %lld.\n", 
     result, pmatch[1].rm_so, pmatch[1].rm_eo - 1); 

// later on ... 
free(result); 
+0

当我运行上面的操作时,出现错误。 test.c:在函数'main'中: test.c:21:warning:字段精度应该是'int'类型,但是参数2的类型是'regoff_t' test.c:21:warning:format'%d '期望类型'int',但参数4的类型'regoff_t' test.c:21:warning:格式'%d'期望类型'int',但参数5类型'regoff_t'' – user983223

+0

这很奇怪,因为这在我的网站上完美运行,甚至使用不同的gcc版本......你确定你使用了完全相同的代码吗? – Stefan

+0

@ user983223首先,这些是警告,而不是错误,但我同意你的看法,它们很丑,并且避免警告消息可以被认为是强制性的。看看我的编辑如何避免这些... – Stefan

1

结果匹配(您的group)为您提供了开始索引和结束索引。你只需要打印这两个indeces之间的项目。

group[0]将是整个正则表达式的匹配。随后的组将会是你在正则表达式中的任何捕获。

for(int i = 0; i < re_links.re_nsub; ++i) { 
    printf("match %d from index %d to %d: ", i, group[i].rm_so, group[i].rm_eo); 

    for(int j = group[i].rm_so; j < group[i].rm_eo; ++j) { 
     printf("%c", line[j]); 
    } 
    printf("\n"); 
} 

有关完整的示例,请参阅我的回答here