【问题标题】:Count number of matches using regex.h in C在 C 中使用 regex.h 计算匹配数
【发布时间】:2016-05-02 04:30:32
【问题描述】:

我在 C 中使用 POSIX 正则表达式 regex.h 来计算一个短语在英语文本片段中出现的次数。 但是regexec(...) 的返回值仅说明是否找到匹配项。所以我尝试使用nmatchmatchptr 来查找不同的外观,但是当我从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 cat is in the bathroom 中正则表达式 (the) 的两个不同匹配项?

【问题讨论】:

    标签: c regex


    【解决方案1】:

    您错误地理解了pmatch 的含义。它不用于获取重复的模式匹配。它用于获取一个匹配项及其可能子组的位置。正如regcomp(3) 的 Linux 手册所说:

    从第 i 个 open 开始的子表达式的偏移量 括号存储在 pmatch[i] 中。整个正则表达式的匹配地址存储在 匹配[0]。 (请注意,要返回 N 个子表达式匹配的偏移量,nmatch 必须至少为 N+1。) 任何未使用的结构元素都将包含值 -1。

    如果你有正则表达式this (\w+) costs (\d+) USD,那么在括号(\w+)(\d+)中有2个捕获组;现在,如果 nmatch 至少设置为 3,pmatch[0] 将包含整个匹配的开始和结束索引,pmatch[1] 开始和结束 (\w+) 组和 pmatch[2] 用于 (\d+) 组。


    如果模式从不匹配,则以下代码应打印连续匹配的范围(如果有)或字符串"&lt;the input string&gt;" 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的一个子匹配,如果你没有这些括号,你的代码会只打印了第一次匹配的位置)。

    【讨论】:

    • 谢谢你的解释,我现在明白了这些参数的含义,但我也想知道我们在c中使用regex.h时有没有办法确定匹配的计数,谢谢你非常喜欢。
    • 非常感谢,所以下次也可以用指针sz来确定regexec的起点,我现在明白了,非常感谢:D。
    • @huynguyen 是的,有了这个功能,这是唯一的方法。
    • @huynguyen ahha,修复了 eflags 的东西
    • 好的,确保它与^ 一起正常工作 - 仅在开头匹配。
    猜你喜欢
    • 2020-09-11
    • 2020-09-28
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    • 2015-06-25
    • 2017-03-02
    相关资源
    最近更新 更多