来源: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(®ex,pattern1,REG_EXTENDED);
if(reti){
fprintf(stderr,"could not compilen");
exit(EXIT_FAILURE);
}
reti = regexec(®ex,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,®ex,msgbuf,sizeof(msgbuf));
fprintf(stderr,"Regex match failed: %sn",msgbuf);
exit(EXIT_FAILURE);
}
regfree(®ex);
exit(EXIT_SUCCESS);
}
输出
szso=3
szeo=11
group1: barbeque
预期有两个组,所以group1只返回bar
。
问题更新:
pattern2
按预期再次匹配sz2
行为- 但是,如果只有模式的一部分匹配,那么
matches[0]
应与matches[1]
相同 - 那么,在这个新的上下文中,我应该期待
group0
和group1
是一样的吗
阅读手册页。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(®ex, pattern1, REG_EXTENDED);
if (reti)
{
fprintf(stderr, "could not compilen");
exit(EXIT_FAILURE);
}
printf("Nsubs = %zun", regex.re_nsub);
reti = regexec(®ex, 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, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %sn", msgbuf);
exit(EXIT_FAILURE);
}
regfree(®ex);
return(EXIT_SUCCESS);
}
它产生:
Nsubs = 0
szso[0]=6
szeo[0]=14
group[0]: [world te]
因为正则表达式中没有分组括号,所以没有子群——您获得的唯一信息是关于整个匹配文本的信息。
如果您使用问题中的pattern2
作为正则表达式,并使用两个带括号的子表达式,那么当数据匹配时,您将在matches
数组中获得更多数据。
通过在每次迭代中用null替换整个buff
数组,复制在这个样本数据上不被null终止是没有问题的。明智的做法是确保它不会在现实生活中的代码中溢出。
如果正则表达式的两个部分中只有一个匹配(在问题中的pattern2
中(,您将从regexec()
返回一个错误,并且可能不依赖于matches
数组中的任何内容。