我在C中使用POSIX正则表达式regex.h
来计算英语文本片段中短语的出现次数。
但regexec(...)
的返回值仅表示是否找到匹配项。所以我尝试使用nmatch
和matchptr
来查找不同的外观,但是当我打印出来自matchptr
的匹配项时,我刚收到第一个短语的第一个索引出现在我的文本中。
这是我的代码:
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
#define MAX_MATCHES 20 //The maximum number of matches allowed in a single string
void match(regex_t *pexp, char *sz) {
regmatch_t matches[MAX_MATCHES];
if (regexec(pexp, sz, MAX_MATCHES, matches, 0) == 0) {
for(int i = 0; i < MAX_MATCHES; i++)
printf("\"%s\" matches characters %d - %d\n", sz, matches[i].rm_so, matches[i].rm_eo);
}
else {
printf("\"%s\" does not match\n", sz);
}
}
int main(int argc, char* argv[]) {
int rv;
regex_t exp;
rv = regcomp(&exp, "(the)", REG_EXTENDED | REG_ICASE);
if (rv != 0) {
printf("regcomp failed\n");
}
match(&exp, "the cat is in the bathroom.");
regfree(&exp);
return 0;
}
如何让此代码报告字符串(the)
中正则表达式the cat is in the bathroom
的两个不同匹配?
答案 0 :(得分:5)
您已正确理解pmatch
的含义。它不用于获取重复的模式匹配。它用于获取一个匹配的位置及其可能的子组。正如regcomp(3)
的Linux手册所说:
从第i个开始开始的子表达式的偏移量 括号存储在pmatch [i]中。整个正则表达式的匹配地址存储在 pmatch [0]。 (注意,要返回N个子表达式匹配的偏移量,nmatch必须至少为N + 1.) 任何未使用的结构元素都将包含值-1。
如果您有正则表达式this (\w+) costs (\d+) USD
,则括号(\w+)
和(\d+)
中有2个捕获组;现在,如果nmatch
设置为至少3,则pmatch[0]
将包含整个匹配的开始和结束索引,pmatch[1]
组的(\w+)
开始和结束以及{pmatch[2]
1}}用于(\d+)
组。
以下代码应打印连续匹配的范围(如果有),如果模式从不匹配,则打印字符串"<the input string>" does not contain a match
。
它经过精心构造,因此它也适用于零长度正则表达式(空正则表达式,或者说正则表达式#?
将匹配每个字符位置,包括在最后一个字符之后; 28个匹配将为输入the cat is in the bathroom.
)
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>
void match(regex_t *pexp, char *sz) {
// we just need the whole string match in this example
regmatch_t whole_match;
// we store the eflags in a variable, so that we can make
// ^ match the first time, but not for subsequent regexecs
int eflags = 0;
int match = 0;
size_t offset = 0;
size_t length = strlen(sz);
while (regexec(pexp, sz + offset, 1, &whole_match, eflags) == 0) {
// do not let ^ match again.
eflags = REG_NOTBOL;
match = 1;
printf("range %zd - %zd matches\n",
offset + whole_match.rm_so,
offset + whole_match.rm_eo);
// increase the starting offset
offset += whole_match.rm_eo;
// a match can be a zero-length match, we must not fail
// to advance the pointer, or we'd have an infinite loop!
if (whole_match.rm_so == whole_match.rm_eo) {
offset += 1;
}
// break the loop if we've consumed all characters. Note
// that we run once for terminating null, to let
// a zero-length match occur at the end of the string.
if (offset > length) {
break;
}
}
if (! match) {
printf("\"%s\" does not contain a match\n", sz);
}
}
int main(int argc, char* argv[]) {
int rv;
regex_t exp;
rv = regcomp(&exp, "(the)", REG_EXTENDED | REG_ICASE);
if (rv != 0) {
printf("regcomp failed\n");
}
match(&exp, "the cat is in the bathroom.");
regfree(&exp);
return 0;
}
P.S。,在这种情况下,你的正则表达式(the)
中的括号是不必要的;你可以写the
(你最初在同一位置获得2场比赛的困惑是因为你得到(the)
的一场比赛和the
的一场比赛,如果你没有这些括号,你的代码只会打印一次匹配的位置。)