POSIX正则表达式 - 括号表达式的零或一个匹配?

时间:2016-09-05 16:30:01

标签: c regex posix

我试图使用正则表达式来解析源文件并在C程序中搜索以" LOG"开头的函数。并且可能会或可能不会跟随类[1248AFM]中的第二个字符,然后是一个左括号。这是在Windows下使用mingw开发的,但最终将使用gcc在Linux下编译和运行。我使用Jan Goyvaerts正则表达式教程作为指导,看起来我之后的是上面显示的括号表达式表达式的零或一个匹配。零或一个听起来很像问号元字符,但在我的实验中,我还没有能够按照括号表达式来工作。为了说明我想要做的事情,我有如下所示的短程序。理想情况下,我想只在str1和str2上匹配。如果我如图所示编译并运行它,我就无法获得任何匹配。如果我在括号表达式后面留下问号,我只在str2上得到一个匹配,这就是我所期望的。除了问号之外,我还尝试了{0,1}形式的区间量词,但也没有成功。我应该使用除括号表达式以外的其他东西吗?

戴夫

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

int main(int argc, char **argv) {
  regex_t regex;
  int rtn = regcomp(&regex, "LOG[1248AFM]?(", 0);
  if (rtn) {
    printf("compile failed\n");
    return(1);
  }
  char *str1 = "  LOG(";
  char *str2 = "  LOGM(";
  char *str3 = "  LOG";
  char *str4 = "  LOGJ(";

  int rtn1 = regexec(&regex, str1, 0, NULL, 0);
  int rtn2 = regexec(&regex, str2, 0, NULL, 0);
  int rtn3 = regexec(&regex, str3, 0, NULL, 0);
  int rtn4 = regexec(&regex, str4, 0, NULL, 0);
  printf("str1: %d\nstr2: %d\nstr3: %d\nstr4: %d\n",
    rtn1, rtn2, rtn3, rtn4);

  return(0);
}

2 个答案:

答案 0 :(得分:2)

像Casimir et Hippolyte所说的那样:当我做评论时,你需要逃脱逃过我的?。问题是你使用字符串文字,这意味着你必须逃避转义。

用户kdhp正确指出

编辑?是基本正则表达式的Gnu扩展名。但问题仍然存在:需要逃避C语言中的转义。

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

int main(int argc, char **argv) {
  regex_t regex;
  // Gnu extension
  // int rtn = regcomp(&regex, "LOG[1248AFM]\\?(",0);
  // Basic regular expression
  int rtn = regcomp(&regex, "LOG[1248AFM]\\{0,1\\}(",0);
  if (rtn) {
    printf("compile failed\n");
    return(1);
  }
  char *str1 = "  LOG(";
  char *str2 = "  LOGM(";
  char *str3 = "  LOG";
  char *str4 = "  LOGJ(";

  int rtn1 = regexec(&regex, str1, 0, NULL, 0);
  int rtn2 = regexec(&regex, str2, 0, NULL, 0);
  int rtn3 = regexec(&regex, str3, 0, NULL, 0);
  int rtn4 = regexec(&regex, str4, 0, NULL, 0);
  printf("str1: %d\nstr2: %d\nstr3: %d\nstr4: %d\n",
    rtn1, rtn2, rtn3, rtn4);

  return(0);
}

给出

str1: 0
str2: 0
str3: 1
str4: 1

答案 1 :(得分:2)

这里的部分问题源于不同正则表达方言的特征集之间的不幸混淆。

长话短说,使用REG_EXTENDED,您可以获得某些正则表达式构造的grep -E(又名egrep)含义。

"e?(grep){3,7}"

不需要反斜杠 - 问号?使前一个表达式可选,括号进行分组,花括号表示广义重复(在这种情况下,重复三到七次)。

如果没有REG_EXTENDED,您将获得BRE语义,这需要在每个语句之前使用反斜杠。当然,在C字符串中,为了产生一个文字反斜杠,你需要两个反斜杠,因为反斜杠是一个通用的C字符串转义字符。

"e\\?\\(grep\\)\\{3,7\\}"

接下来是对历史的简要解释,但你可以在这里停止阅读并完成。

基本正则表达式(BRE)基于Ken Thompson的原始grep的功能集。原始grep没有分组括号,带有大括号的广义量化,甚至没有表达可选性的问号。然而,POSIX标准编码了一种表达这些结构的方法,即使在BRE中也是如此。坚持下去。

扩展正则表达式(ERE)基于egrep的特征集,其主要是Al Aho的grep的扩展。它引入了许多新功能,以及不同的内部架构,基于当时对自动机理论应用于字符串匹配的持续研究(我们在这里谈论早期到中期)。

当这些由POSIX标准化时,标准引入了特征奇偶校验,但这些方言的表面语法不同。在BRE方言中引入了grep语法的某种古怪扩展,其中反斜杠启用,而不是转义,某些字符的特殊含义。这使得BRE向后兼容原始grep(只要您不必在正则表达式中使用反斜杠,之前它们没有特殊含义),这是一个重要的考虑因素,但无可否认是设计疣。 / p>