使用POSIX正则表达式函数捕获C中的正则表达式模式组



来源:https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-POSIX-REGEXP

我试图在C中模仿以下两个SQL查询。第一个有效;第二个失败:

SELECT regexp_match('hello world test', 'world.{3}');   
SELECT regexp_match('foobarbequebaz', '(bar)(beque)');     

#include<regex.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_MATCHES 1024
int main(void)
{
regex_t regex;
int reti;
char msgbuf[100];
char buff0[20];
char buff[20];
char buff1[20];
char *sz1 = "hello world test";
//char *sz2= "foobarbequebaz";
char *pattern1 = "world.{3}";
//char *pattern2 = "(bar)(beque)";
regmatch_t matches[MAX_MATCHES];
/* Compile regular expression */
reti = regcomp(&regex,pattern1,REG_EXTENDED);
if(reti){
fprintf(stderr,"could not compilen");
exit(EXIT_FAILURE);
}
reti = regexec(&regex,sz1,MAX_MATCHES,matches,0);
if(!reti){
printf("szso=%dn",matches[1].rm_so);
printf("szeo=%dn",matches[1].rm_eo);
memcpy(buff0,sz1+matches[0].rm_so,matches[0].rm_eo-matches[0].rm_so);
memcpy(buff,sz1+matches[1].rm_so,matches[1].rm_eo-matches[1].rm_so);
memcpy(buff1,sz1+matches[2].rm_so,matches[2].rm_eo-matches[2].rm_so);
printf("group0: %sn",buff0);
printf("group1: %sn",buff);
printf("group2: %sn",buff1);
}
else if(reti == REG_NOMATCH){
puts("No match");
}
else{
regerror(reti,&regex,msgbuf,sizeof(msgbuf));
fprintf(stderr,"Regex match failed: %sn",msgbuf);
exit(EXIT_FAILURE);
}
regfree(&regex);
exit(EXIT_SUCCESS);
}

输出

szso=3
szeo=11
group1: barbeque

预期有两个组,所以group1只返回bar


问题更新:

  • pattern2按预期再次匹配sz2行为
  • 但是,如果只有模式的一部分匹配,那么matches[0]应与matches[1]相同
  • 那么,在这个新的上下文中,我应该期待group0group1是一样的吗

阅读手册页。matches[0]包含整个匹配,matches[1]包含第一个带括号的组,matches[2]包含第二个,依此类推

请注意,memcpy()提供的是字节数组,而不是字符串。如果不做一些额外的工作,就无法在printf()语句中可靠地使用buff。您可以使用:

int i = 0;
int len = matches[i].rm_eo - matches[i].rm_so;
printf("group1 [%*.*s]n", len, len, sz2);

或者你可以使用:

printf("group1 [%*.*s]n", len, len, buff);

只打印数据的相关部分。注意nwellnhof在他们的回答中的注释——这就是我将变量i添加到混合中的原因:您可以迭代匹配。

这个代码对我有效:

#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_MATCHES 10
int main(void)
{
regex_t regex;
int reti;
char msgbuf[100];
char *sz1 = "hello world test";
char *pattern1 = "world.{3}";
regmatch_t matches[MAX_MATCHES];
/* Compile regular expression */
reti = regcomp(&regex, pattern1, REG_EXTENDED);
if (reti)
{
fprintf(stderr, "could not compilen");
exit(EXIT_FAILURE);
}
printf("Nsubs = %zun", regex.re_nsub);
reti = regexec(&regex, sz1, MAX_MATCHES, matches, 0);
if (!reti)
{
for (size_t i = 0; i <= regex.re_nsub; i++)
{
char buff[20] = "";
printf("szso[%zu]=%lldn", i, matches[i].rm_so);
printf("szeo[%zu]=%lldn", i, matches[i].rm_eo);
memcpy(buff, sz1 + matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so);
printf("group[%zu]: [%s]n", i, buff);
}
}
else if (reti == REG_NOMATCH)
{
puts("No match");
}
else
{
regerror(reti, &regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %sn", msgbuf);
exit(EXIT_FAILURE);
}
regfree(&regex);
return(EXIT_SUCCESS);
}

它产生:

Nsubs = 0
szso[0]=6
szeo[0]=14
group[0]: [world te]

因为正则表达式中没有分组括号,所以没有子群——您获得的唯一信息是关于整个匹配文本的信息。

如果您使用问题中的pattern2作为正则表达式,并使用两个带括号的子表达式,那么当数据匹配时,您将在matches数组中获得更多数据。

通过在每次迭代中用null替换整个buff数组,复制在这个样本数据上不被null终止是没有问题的。明智的做法是确保它不会在现实生活中的代码中溢出。

如果正则表达式的两个部分中只有一个匹配(在问题中的pattern2中(,您将从regexec()返回一个错误,并且可能不依赖于matches数组中的任何内容。

相关内容

  • 没有找到相关文章

最新更新