web-dev-qa-db-ja.com

正規表現を使用してグループをどのようにキャプチャしますか?

正規表現を使用して別の文字列から文字列を抽出しようとしています。 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);になります

ありがとう:)

26
Sylvain

お気づきのとおり、regmatch_t構造体のpmatch配列の0番目の要素には、一致した文字列全体の境界が含まれます。あなたの例では、部分式による文字列の一致に関する情報を取得するために、インデックス0ではなくインデックス1のregmatch_tに関心があります。

さらにヘルプが必要な場合は、質問を編集して実際の小さなコードサンプルを含めて、問題をより簡単に見つけられるようにしてください。

10
RarrRarrRarr

これは、複数のグループのキャプチャを示すコード例です。

グループ「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
18
Ian Mackinnon