Подтвердить что ты не робот

Как вы захватываете группу с регулярным выражением?

Я пытаюсь извлечь строку из другого с помощью regex. Я использую функции регулярного выражения POSIX (regcomp, regexec...), и я не могу захватить группу...

Например, пусть шаблон будет таким простым, как "MAIL FROM:<(.*)>"
REG_EXTENDED cflags)

Я хочу захватить все между '<' и ' > '

Моя проблема в том, что regmatch_t дает мне границы всего шаблона (MAIL FROM: <... > ) вместо того, что между скобками...

Что мне не хватает?

Спасибо заранее,

изменить: код

#define SENDER_REGEX "MAIL FROM:<(.*)>"

int main(int ac, char **av)
{
  regex_t regex;
  int status;
  regmatch_t pmatch[1];

  if (regcomp(&regex, SENDER_REGEX, REG_ICASE|REG_EXTENDED) != 0)
    printf("regcomp error\n");
  status = regexec(&regex, av[1], 1, pmatch, 0);
  regfree(&regex);
  if (!status)
      printf(  "matched from %d (%c) to %d (%c)\n"
             , pmatch[0].rm_so
             , av[1][pmatch[0].rm_so]
             , pmatch[0].rm_eo
             , av[1][pmatch[0].rm_eo]
            );

  return (0);
}

<сильные > выходы:

$./a.out "012345MAIL FROM:<abcd>$"
matched from 6 (M) to 22 ($)

Решение:

как сказал RarrRarrRarr, индексы действительно находятся в pmatch[1].rm_so и pmatch[1].rm_eo
следовательно, regmatch_t pmatch[1]; становится regmatch_t pmatch[2];
и regexec(&regex, av[1], 1, pmatch, 0); становится regexec(&regex, av[1], 2, pmatch, 0);

Спасибо:)

4b9b3361

Ответ 1

0-й элемент массива pmatch структур regmatch_t будет содержать границы всей строки, сопоставленной, как вы заметили. В вашем примере вас интересует regmatch_t по индексу 1, а не по индексу 0, чтобы получить информацию о совпадении строк по подвыражению.

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

Ответ 2

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

Вы можете видеть, что группа "0" - это полное совпадение, а последующие группы - это части в круглых скобках.

Обратите внимание, что это только фиксирует первое совпадение в исходной строке. Здесь версия, которая захватывает несколько групп в нескольких совпадениях.

#include <stdio.h>
#include <string.h>
#include <regex.h>

int main ()
{
  char * source = "___ abc123def ___ ghi456 ___";
  char * regexString = "[a-z]*([0-9]+)([a-z]*)";
  size_t maxGroups = 3;

  regex_t regexCompiled;
  regmatch_t groupArray[maxGroups];

  if (regcomp(&regexCompiled, regexString, REG_EXTENDED))
    {
      printf("Could not compile regular expression.\n");
      return 1;
    };

  if (regexec(&regexCompiled, source, maxGroups, groupArray, 0) == 0)
    {
      unsigned int g = 0;
      for (g = 0; g < maxGroups; g++)
        {
          if (groupArray[g].rm_so == (size_t)-1)
            break;  // No more groups

          char sourceCopy[strlen(source) + 1];
          strcpy(sourceCopy, source);
          sourceCopy[groupArray[g].rm_eo] = 0;
          printf("Group %u: [%2u-%2u]: %s\n",
                 g, groupArray[g].rm_so, groupArray[g].rm_eo,
                 sourceCopy + groupArray[g].rm_so);
        }
    }

  regfree(&regexCompiled);

  return 0;
}

Вывод:

Group 0: [ 4-13]: abc123def
Group 1: [ 7-10]: 123
Group 2: [10-13]: def