Regexp в C - матч группы - PullRequest
       12

Regexp в C - матч группы

2 голосов
/ 05 января 2011

Я боролся с регулярными выражениями в C (просто /usr/include/regex.h).


У меня есть (скажем,) сотни регулярных выражений, и одно из них может соответствовать входной строке.В настоящее время я делаю это (генерируя это на самом деле) так: сотни тренировок с совпадением внутри, разрыв, если не совпадает, и переход к другому.Один за другим:

do {
    if ( regex_match(str, my_regex1) != MY_REGEX_SUCCESS ) DO_FAIL; //break
    ...
    if ( sscanf(str, " %d.%d.%d.%d / %d ", &___ip1, &___ip2, &___ip3, &___ip4, &___pref) != 5 ) DO_FAIL; //break
    ...
} while (0);

do {
    if ( regex_match(str, my_regex2) != MY_REGEX_SUCCESS ) DO_FAIL; //break
    ...
    ...
} while (0);

do {
    if ( regex_match(str, my_regex3) != MY_REGEX_SUCCESS ) DO_FAIL; //break
    ...
    ...
} while (0);

Я хотел бы получить что-то вроде:

const char * match1 = "^([[:space:]]*)([$]([._a-zA-Z0-9-]{0,118})?[._a-zA-Z0-9])([[:space:]]*)$";
const char * match2 = "^([[:space:]]*)(target|origin)([[:space:]]*):([[:space:]]*)([$]([._a-zA-Z0-9-]{0,118})?[._a-zA-Z0-9])([[:space:]]*):([[:space:]]*)\\*([[:space:]]*)$";
const char * match3 = "^([[:space:]]*)(target|origin)([[:space:]]*):([[:space:]]*)([$]([._a-zA-Z0-9-]{0,118})?[._a-zA-Z0-9])([[:space:]]*)/([[:space:]]*)(([0-2]?[0-9])|(3[0-2]))([[:space:]]*):([[:space:]]*)(([1-9][0-9]{0,3})|([1-5][0-9]{4})|(6[0-4][0-9]{3})|(65[0-4][0-9]{2})|(655[0-2][0-9])|(6553[0-5]))([[:space:]]*)$";
char * my_match;
asprintf(&my_match, "(%s)|(%s)|(%s)", match1, match2, match3);


int num_gr = give_me_number_of_regex_group(str, my_match)
switch (num_gr) {
    ...
}

и не знаю, как это сделать ...

Есть предложения?
Спасибо!

Ответы [ 3 ]

5 голосов
/ 05 января 2011

Я предполагаю, что ваша regex_match - это некоторая комбинация regcomp и regexec.Чтобы включить группировку, необходимо вызвать regcomp с флагом REG_EXTENDED, но без флага REG_NOSUB (в третьем аргументе).

regex_t compiled;
regcomp(&compiled, "(match1)|(match2)|(match3)", REG_EXTENDED);

Затем выделить место для групп.Количество групп хранится в compiled.re_nsub.Передайте это число regexec:

size_t ngroups = compiled.re_nsub + 1;
regmatch_t *groups = malloc(ngroups * sizeof(regmatch_t));
regexec(&compiled, str, ngroups, groups, 0);

Теперь первой недопустимой группой является группа со значением -1 в обоих полях rm_so и rm_eo:

size_t nmatched;
for (nmatched = 0; nmatched < ngroups; nmatched++)
    if (groups[nmatched].rm_so == (size_t)(-1))
        break;

nmatched - количество соответствующих вложенных выражений (групп) в скобках.Добавьте свою собственную проверку ошибок.

0 голосов
/ 05 января 2011

«У меня есть (скажем, сотни регулярных выражений ...»

Похоже, вы пытаетесь сравнить четверные части IP-адресов.Как правило, при использовании регулярных выражений обычно используется красный флаг при использовании такого количества регулярных выражений для одной цели и остановка после совпадения.

пример: какая группа будет правильно соответствовать первой?
target ~'American' , pattern ~ /(Ame)|(Ameri)|(American)/
Это даже не включает квантификаторы в подгруппах.

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

0 голосов
/ 05 января 2011

Вы можете получить от них массив строк, содержащих ваши регулярные выражения, и протестировать каждую из них.

//count is the number of regexps provided
int give_me_number_of_regex_group(const char *needle,const char** regexps, int count ){
  for(int i = 0; i < count; ++i){
    if(regex_match(needle, regexp[i])){
      return i;
    }
  }
  return -1; //didn't match any
}

или я что-то наблюдаю?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...