views:

770

answers:

1

Hi, I am inexperienced with using C, and I need to use PCRE to get matches.
Here is a sample of my source code:

int test2()
    {
        const char *error;
            int   erroffset;
            pcre *re;
            int   rc;
            int   i;
            int   ovector[OVECCOUNT];

        char *regex = "From:([^@]+)@([^\r]+)";
            char str[]  = "From:[email protected]\r\n"\
                      "From:[email protected]\r\n"\
                      "From:[email protected]\r\n";

      re = pcre_compile (
             regex,       /* the pattern */
             0,                    /* default options */
             &error,               /* for error message */
             &erroffset,           /* for error offset */
             0);                   /* use default character tables */

      if (!re) {
        printf("pcre_compile failed (offset: %d), %s\n", erroffset, error);
        return -1;
      }

      rc = pcre_exec (
        re,                   /* the compiled pattern */
        0,                    /* no extra data - pattern was not studied */
        str,                  /* the string to match */
        strlen(str),          /* the length of the string */
        0,                    /* start at offset 0 in the subject */
        0,                    /* default options */
        ovector,              /* output vector for substring information */
        OVECCOUNT);           /* number of elements in the output vector */

      if (rc < 0) {
        switch (rc) {
          case PCRE_ERROR_NOMATCH:
            printf("String didn't match");
            break;

          default:
            printf("Error while matching: %d\n", rc);
            break;
        }
        free(re);
        return -1;
      }

      for (i = 0; i < rc; i++) {
        printf("%2d: %.*s\n", i, ovector[2*i+1] - ovector[2*i], str + ovector[2*i]);
      }
    }

In this demo, the output is only:

0: From:[email protected]
1: regular.expressions
2: example.com

I want to output all of the matches; how can I do that?

+1  A: 

I use a class to wrap PCRE to make this easier, but after the pcre_exec, the ovector contains the substring indexes you need to find the matches within the original string.

So it would be something like:

#include <string>
#include <iostream>
#include "pcre.h"

int main (int argc, char *argv[])
{
    const char *error;
    int   erroffset;
    pcre *re;
    int   rc;
    int   i;
    int   ovector[100];

    char *regex = "From:([^@]+)@([^\r]+)";
    char str[]  = "From:[email protected]\r\n"\
                  "From:[email protected]\r\n"\
                  "From:[email protected]\r\n";

    re = pcre_compile (regex,          /* the pattern */
                       PCRE_MULTILINE,
                       &error,         /* for error message */
                       &erroffset,     /* for error offset */
                       0);             /* use default character tables */
    if (!re)
    {
        printf("pcre_compile failed (offset: %d), %s\n", erroffset, error);
        return -1;
    }

    unsigned int offset = 0;
    unsigned int len    = strlen(str);
    while (offset < len && (rc = pcre_exec(re, 0, str, len, offset, 0, ovector, sizeof(ovector))) >= 0)
    {
        for(int i = 0; i < rc; ++i)
        {
            printf("%2d: %.*s\n", i, ovector[2*i+1] - ovector[2*i], str + ovector[2*i]);
        }
        offset = ovector[1];
    }
    return 1;
}
RC
Thanks for your answer.But i still do not know how to output all the matches.
tbmvp
Are you only getting the first set of matcheS? You will have to specify the PCRE_MULTILINE option when you compile the regex. See: http://www.pcre.org/pcre.txt for details. I'll update the example.
RC
I've updated the code in my answer to do what I think you need. I'm admittedly not a PCRE expert as I've only used it through a wrapper so I'm not familiar with it's intricacies. I would think there would be a way to do this with 1 call to exec. and have it return the ovector array with string indexes to all the matches. This should do the trick though.
RC
Thanks very much for your help, i will read the PCRE documents again.
tbmvp