简体   繁体   中英

posix regular expression for parsing uevent causing error

I am trying to parse uevent using this below code but I think my regular expression is not proper causing regcomp function to fail.

Can anyone help? I am trying to do something like this .

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

int main ()
{
  char * source = "change@/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
  char * regexString = "(?<action>[a-zA-Z]+)@\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
  size_t maxGroups = 4;

  regex_t regexCompiled;
  regmatch_t groupArray[maxGroups];

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

  return 0; 
}

I am getting "Could not compile regular expression.". It means regcomp didn't recognize the regex.

When I report on the error using the code:

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

int main(void)
{
  //char * source = "change@/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
  char * regexString = "(?<action>[a-zA-Z]+)@\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
  //size_t maxGroups = 4;

  regex_t regexCompiled;
  //regmatch_t groupArray[maxGroups];

  int rc;
  if ((rc = regcomp(&regexCompiled, regexString, REG_EXTENDED)) != 0)
    {
      char buffer[1024];
      regerror(rc, &regexCompiled, buffer, sizeof(buffer));
      printf("Could not compile regular expression (%d: %s).\n", rc, buffer);
      return 1;
    }
  regfree(&regexCompiled);

  return 0; 
}

I get the output:

Could not compile regular expression (13: repetition-operator operand invalid).

The problem is in the notation (? you are using:

"(?<action>[a-zA-Z]+)@\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)"

That notation is for PCRE and not POSIX. And PCRE uses ? after ( precisely because it isn't valid in other regex systems (such as POSIX).

So, if you want to use PCRE regexes, install and use the PCRE library.

Otherwise, you'll need to use:

"([a-zA-Z]+)@\\/(.*)\\/([a-zA-z]+)\\/([a-zA-z]+)"

With that in place, and noting that you need a regmatch_t for the whole of the string that's matched plus 4 captured groups (for a total of 5 captures), you can write:

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

int main(void)
{
    char *source = "change@/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
    // char * regexString = "(?<action>[a-zA-Z]+)@\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
    size_t maxGroups = 5;
    char *regexString =  "([a-zA-Z]+)@\\/(.*)\\/([a-zA-z]+)\\/([a-zA-z]+)";

    regex_t regexCompiled;
    regmatch_t groupArray[maxGroups];

    int rc;
    if ((rc = regcomp(&regexCompiled, regexString, REG_EXTENDED)) != 0)
    {
        char buffer[1024];
        regerror(rc, &regexCompiled, buffer, sizeof(buffer));
        printf("Could not compile regular expression (%d: %s).\n", rc, buffer);
        return 1;
    }
    if ((rc = regexec(&regexCompiled, source, maxGroups, groupArray, 0)) != 0)
    {
        char buffer[1024];
        regerror(rc, &regexCompiled, buffer, sizeof(buffer));
        printf("Could not execute regular expression (%d: %s).\n", rc, buffer);
        return 1;
    }

    printf("Match successful:\n");
    for (size_t i = 0; i < maxGroups; i++)
    {
        int so = groupArray[i].rm_so;
        int eo = groupArray[i].rm_eo;
        printf("%zu: %d..%d [%.*s]\n", i, so, eo, eo - so, &source[so]);
    }

    regfree(&regexCompiled);

    return 0;
}

and the output is:

Match successful:
0: 0..64 [change@/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery]
1: 0..6 [change]
2: 8..43 [devices/soc/799999.i2c/i2c-3/3-0015]
3: 44..56 [power_supply]
4: 57..64 [battery]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM