Используйте GNU libc regexec() для подсчета подстроки

Можно ли подсчитать, сколько раз подстрока появляется в строке, используя сопоставление регулярных выражений с GNU libc regexec()?


person jackhab    schedule 11.03.2009    source источник


Ответы (3)


Нет, regexec() находит только одно совпадение за вызов. Если вы хотите найти следующее совпадение, вы должны снова вызвать его дальше по строке.

Если вы хотите искать только простые подстроки, лучше использовать стандартную функцию C string.h strstr(); тогда вам не придется беспокоиться об экранировании специальных символов регулярных выражений.

person bobince    schedule 11.03.2009

regexec возвращает в своем четвертом параметре "pmatch" структуру со всеми совпадениями. "pmatch" - это структура фиксированного размера, если совпадений больше, вы вызовете функцию в другой раз.

Я нашел этот код с двумя вложенными циклами и изменил его. Оригинальный код вы можете найти на http://www.lemoda.net/c/unix-regex/index.html:

static int match_regex (regex_t * r, const char * to_match)
{
    /* "P" is a pointer into the string which points to the end of the
       previous match. */
    const char * p = to_match;
    /* "N_matches" is the maximum number of matches allowed. */
    const int n_matches = 10;
    /* "M" contains the matches found. */
    regmatch_t m[n_matches];
    int number_of_matches = 0;
    while (1) {
        int i = 0;
        int nomatch = regexec (r, p, n_matches, m, 0);
        if (nomatch) {
            printf ("No more matches.\n");
            return nomatch;
        }
        for (i = 0; i < n_matches; i++) {
            if (m[i].rm_so == -1) {
                break;

            }
            number_of_matches ++;
        }
        p += m[0].rm_eo;
    }
    return number_of_matches ;
}
person Oscar Raig Colon    schedule 28.11.2012

извините за создание еще одного ответа, потому что у меня не 50 репутации. Я не могу комментировать ответ @Oscar Raig Colon.

pmatch не может соответствовать всем подстрокам, pmatch используется для сохранения смещения для подвыражения, ключ в том, чтобы понять, что такое подвыражение, подвыражение "\(\)" в BRE, "()" в ERE. если во всем регулярном выражении нет подвыражения, regexec() возвращает только смещение первой строки совпадения и помещает его в pmatch[0].

вы можете найти пример на [http://pubs.opengroup.org/onlinepubs/007908799/xsh/regcomp.html%5d%5b1%5d

Далее показано, как можно использовать флаг REG_NOTBOL с regexec() для поиска всех подстрок в строке, которые соответствуют шаблону, указанному пользователем. (Для простоты примера выполняется очень небольшая проверка ошибок.)

(void) regcomp (&re, pattern, 0);
/* this call to regexec() finds the first match on the line */
error = regexec (&re, &buffer[0], 1, &pm, 0);
while (error == 0) {    /* while matches found */
    /* substring found between pm.rm_so and pm.rm_eo */
    /* This call to regexec() finds the next match */
    error = regexec (&re, buffer + pm.rm_eo, 1, &pm, REG_NOTBOL);
}
person brytonlee01    schedule 27.06.2014