这是我遇到的C函数:
char get_access_token(char *client_credentials)
{
regex_t regex;
int reti;
char msgbuf[100];
reti = regcomp(®ex, "\\\"access_token\\\".\\\"(.*?)\\\"", 0);
regmatch_t pmatch[1];
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
reti = regexec(®ex, client_credentials, 1, pmatch, 0);
if (!reti) {
puts("Match");
} else if (reti == REG_NOMATCH) {
puts("No match");
} else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
return (char) "";
}
我要解析的字符串是JSON字符串,我不在乎实际结构,我只在乎访问令牌。
它应该看起来像这样:
{"access_token": "blablablabal"}
我希望我的函数只返回“ blablablabla”
我要使用的RegEx是这样的:
\"access_token"."(.*?)"
但是我无法在变量pmatch
中找到该数组中的两个数字,我真的不知道这些数字是什么意思。
我在做什么错?
P.S。我是C菜鸟,我在学习。
答案 0 :(得分:1)
有几个问题。您的正则表达式中有错别字。而且您正在尝试将扩展的正则表达式功能与POSIX正则表达式一起使用。
首先是错别字。
reti = regcomp(®ex, "\\\"access_token\\\".\\\"(.*?)\\\"", 0);
^
应该是:
reti = regcomp(®ex, "\\\"access_token\\\": \\\"(.*?)\\\"", 0);
然后,我们不需要在正则表达式中转义引号。这样更易于阅读。
reti = regcomp(®ex, "\"access_token\": \"(.*?)\"", 0);
这仍然不起作用,因为它使用的是基本POSIX正则表达式所没有的功能。捕获组必须在基本POSIX正则表达式中转义。可以使用REG_EXTENDED
来解决。 *?
非贪婪运算符是从Perl借来的增强的non-POSIX功能。您可以通过REG_ENHANCED
获得它们。
reti = regcomp(®ex, "\"access_token\": \"(.*?)\"", REG_ENHANCED|REG_EXTENDED);
但出于所有相同的原因,we don't parse HTML with a regex请勿尝试使用正则表达式解析JSON。使用JSON库,例如json-glib。
答案 1 :(得分:1)
好吧,您的pmatch
数组必须至少包含两个元素,您可能知道,组0是整个匹配的正则表达式,并且填充了整个正则表达式(例如所有正则表达式都用圆括号对进行了舍入)(您想要将组1括起来,所以pmatch[1]
将被第一个子表达式组的信息填充。
如果您查看文档,则pmatch
元素具有两个字段,这些字段索引了与组匹配的原始缓冲区中的起始索引,而则位于最后一个索引之后组中字符串结束的位置。这些字段名称分别为rm_so
和rm_eo
,与pmatch[0]
中的字段名称一样,它们分别表示常规(子)表达式开始和结束处的索引。
您可以使用以下方式打印匹配的元素(一旦知道它们是有效的,请参阅doc):
#define SIZEOF(arr) (sizeof arr / sizeof arr[0])
...
regmatch_t pmatch[2]; /* for global regexp and group 1 */
...
/* you don't need to escape " chars, they are not special for regcomp,
* they do, however, for C, so only one \ must be used. */
res = regcomp(®ex, "\"access_token\".\"([^)]*)\"", 0);
...
reti = regexec(®ex, client_credentials, SIZEOF(pmatch), pmatch, 0);
for (i = 0; i < regex.re_nsub; i++) {
char *p = client_credentials + pmatch[i].rm_so; /* p points to beginning of match */
size_t l = pmatch[i].rm_eo - pmatch[i].rm_so; /* match length */
printf("Group #%d: %0.*s\n", i, l, p);
}
我很抱歉提交一小段代码,而不是一个可验证且完整的示例,但是由于您没有在问题中这样做(因此我们无法测试您的示例代码),因此我不会在答案中这样做。因此,该代码未经测试,可能会出错。提防这一点。
测试样本响应需要时间,如果我们首先使您的样本代码完全可测试,则情况更糟。 (这是对初学者的抱怨-和一些非初学者的-不发布Minimal, Complete, and Verifiable example的使用。)