C/C++正则表达式编程

11 篇文章 0 订阅
7 篇文章 0 订阅
导读:

  GNU/Linux有两套库可用于正则表达式编程:POSIX库和PCRE库。前者不需要单独安装,一般需求还是能满足的,速度稍慢些。后者是久负盛名的Perl正则表达式库,功能强大,匹配速度快,不过可能需要单独安装。

  POSIX库

  如何使用POSIX库的例子:

  #include

  #include

  #include

  char *get_regerror (int errcode, regex_t *compiled)

  {

  size_t length = regerror (errcode, compiled, NULL, 0);

  char *buffer = malloc(length);

  if (!buffer) return NULL;

  (void) regerror (errcode, compiled, buffer, length);

  return buffer;

  }

  int regtest(const char*pattern, const char* string)

  {

  regex_t reg;

  regmatch_t *subexprs = NULL;

  int ret;

  int i;

  if (0 != (ret=regcomp(?, pattern, REG_EXTENDED))) {

  char *buffer = get_regerror(ret, ?);

  if (buffer) {

  fprintf(stderr, "regcomp:[%d]%s/n", ret, buffer);

  free(buffer);

  }

  return -1;

  }

  subexprs = malloc((reg.re_nsub+1)*sizeof(regmatch_t));

  if (!subexprs) {

  fprintf(stderr, "error malloc subexprs/n");

  regfree(?);

  return -1;

  }

  if (0 != (ret=regexec(?, string, reg.re_nsub+1, subexprs, 0))) {

  char *buffer = get_regerror(ret, ?);

  if (buffer) {

  fprintf(stderr, "regexec:[%d]%s/n", ret, buffer);

  free(buffer);

  }

  

  regfree(?);

  return -1;

  }

  for (i = 0; i <= reg.re_nsub; i++) {

  printf("[%d]:", i);

  

  if (subexprs[i].rm_so == subexprs[i].rm_eo) {

  printf("[EMPTY SUBEXPR]/n");

  }

  else if (subexprs[i].rm_so == -1 ||

  subexprs[i].rm_eo == -1) {

  printf("[NO SUBEXPR]/n");

  }

  else {

  fwrite(string+subexprs[i].rm_so, 1,

  subexprs[i].rm_eo-subexprs[i].rm_so, stdout);

  printf("/n");

  }

  }

  regfree(?);

  if (subexprs) free(subexprs);

  return 0;

  }

  int main(int argc, char *argv[])

  {

  if (argc != 3) {

  fprintf(stderr, "Usage: regtest pattern string/n");

  return -1;

  }

  fprintf(stderr, "pattern:%s/n", argv[1]);

  fprintf(stderr, "string:%s/n", argv[2]);

  return regtest(argv[1], argv[2]);

  }

  在字符串匹配之前,必须先 编译匹配模式,这是通过regcomp实现的。这个函数的原型如下:

  int regcomp (regex_t *compiled, const char *pattern, int cflags)

  参数compiled有一个成员需要关注:re_nsub,代表编译后的子表达式数目,由于需要保存整个匹配到的模式,所以最终匹配的条目数是re_nsub加1。cflags用来修饰匹配模式,可取值如下:

  REG_EXTENDED 启用POSIX正则库扩展,关于该扩展的详细信息可参考POSIX规范

  REG_ICASE 忽略大小写

  REG_NOSUB 不要存储子表达式

  REG_NEWLINE 把换行符作为多行的分隔符,这样'$'可匹配每一行的行尾,'^'匹配每一行的行首,'.'不匹配换行符,[^...]不匹配新行

  编译完模式后从内存中分配子表达式存储空间,然后调用regexec对串进行匹配,该函数原型如下:

  int regexec (regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr [], int eflags)

  nmatch指明matchptr数组的数目,该数目是compiled->re_nsub+1,也可以让nmatch为0,matchptr为NULL,表示不要保存子表达式。eflags通常为0。

  匹配结束后,匹配到的子表达式在串中的偏移保存在regmatch_t结构中,该结构有两个成员:

  rm_so 子表达式的起始偏移

  rm_eo 子表达式的结束偏移

  这是一个开区间,实际的子表达式在[rm_so,rm_eo)里。

  如果没有匹配的子表达式,比如"f(o*)"匹配"fum",实际匹配到的只有"f",这时rm_so和rm_eo相等,都为1。如果整个模式在没有子表示式的情况下也能匹配,这时rm_so和rm_eo为-1,比如"ba(na)*"匹配"ba"。

   PCRE库

  PCRE库的功能虽然强大,可是并不难使用。详细信息可参考http://www.pcre.org/里的文档,附录有一个例子,比较全面地阐述了如何调用该库。

  PCRE的子表达式和POSIX类似,不过它还引入了一个 命名子表达式的概念。比如模式"(?P(?P(/d/d)?/d/d)-(?P/d/d)-(?P/d/d))",其中的date, year, month, day是对子表达式的命名。如何根据这些名称来获取子表达式,PCRE文档有详细的说明。

  附录:pcredemo.c

  /*************************************************

  * PCRE DEMONSTRATION PROGRAM *

  *************************************************/

  /* This is a demonstration program to illustrate the most straightforward ways

  of calling the PCRE regular expression library from a C program. See the

  pcresample documentation for a short discussion.

  Compile thuswise:

  gcc -Wall pcredemo.c -I/usr/local/include -L/usr/local/lib /

  -R/usr/local/lib -lpcre

  

  Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and

  library files for PCRE are installed on your system. Only some operating

  systems (e.g. Solaris) use the -R option.

  */

  #include

  #include

  #include

  #define OVECCOUNT 30 /* should be a multiple of 3 */

  int main(int argc, char **argv)

  {

  pcre *re;

  const char *error;

  char *pattern;

  char *subject;

  unsigned char *name_table;

  int erroffset;

  int find_all;

  int namecount;

  int name_entry_size;

  int ovector[OVECCOUNT];

  int subject_length;

  int rc, i;

  /**************************************************************************

  * First, sort out the command line. There is only one possible option at *

  * the moment, "-g" to request repeated matching to find all occurrences, *

  * like Perl's /g option. We set the variable find_all to a non-zero value *

  * if the -g option is present. Apart from that, there must be exactly two *

  * arguments. *

  **************************************************************************/

  find_all = 0;

  for (i = 1; i
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要使用正则表达式,您需要使用一些语法来表示要匹配的文本模式。以下是一些基本的正则表达式语法: 1. 字符匹配 - 用方括号 [] 包括一组字符,表示在这些字符中匹配任意一个字符。例如 [abc] 匹配 a、b 或 c。 - 用横杠 - 表示一个字符范围。例如 [a-z] 匹配任何小写字母。 - 用反斜杠 \ 来转义特殊字符。例如,如果想匹配小数点(.),需要写成 \.。 2. 量词匹配 - 用星号 * 表示匹配前面的字符 0 次或多次。例如 a* 可以匹配 a、aa、aaa 等。 - 用加号 + 表示匹配前面的字符 1 次或多次。例如 a+ 可以匹配 a、aa、aaa 等。 - 用问号 ? 表示匹配前面的字符 0 次或 1 次。例如 a? 可以匹配 a 或空字符串。 3. 分组和捕获 - 用圆括号 () 表示一个分组,可以对分组内的内容进行后续处理。例如 (ab)+ 表示匹配一个或多个连续的 ab。 - 用竖杠 | 表示或者。例如 (a|b) 匹配 a 或 b。 这只是正则表达式语法的基础,正则表达式非常强大且复杂,需要深入学习才能掌握。 ### 回答2: 正则表达式是一种强大的文本匹配工具,可以用于快速、准确地查找和处理字符串。以下是使用正则表达式的一般步骤: 1. 导入正则表达式模块:在使用正则表达式之前,需要先导入相应的模块,比如Python中的re模块。 2. 创建正则表达式:使用合适的语法创建一个符合需求的正则表达式正则表达式由特定字符和符号组成,用于定义某种模式。 3. 创建匹配对象:使用re模块中的函数,如re.compile()编译正则表达式,创建一个匹配对象。这个对象可以根据正则表达式来查找和处理字符串。 4. 匹配模式:利用匹配对象调用相应的方法,如match()、search()、findall()和sub(),根据不同的需求进行模式匹配。 5. 匹配结果处理:根据具体需求,对匹配结果进行处理。可以提取出匹配的字符串、替换指定的字符、或者对匹配结果进行其他操作。 6. 循环匹配:根据实际情况,可以对一个字符串进行多次匹配。可以使用while循环、for循环等方式。 7. 输出或使用:根据需求选择将匹配结果输出到控制台、存入文件,或者在程序中继续使用。 通过上述步骤,我们可以灵活运用正则表达式来查找和处理符合特定模式的字符串。但是需要注意,正则表达式的语法较为繁琐,需要一定的学习和练习。同时,复杂的正则表达式可能会影响程序的性能,因此在使用时需要进行优化和测试。 ### 回答3: 使用正则表达式可以通过以下几个步骤: 1. 导入正则表达式模块:在编程语言中,一般都有支持正则表达式的库或模块,需要先导入相应的模块。 2. 创建正则表达式正则表达式是由一系列字符和特殊字符组成的模式,用于匹配字符串。可以使用特殊字符、元字符和字符类来定义自己需要的模式。 3. 编译正则表达式:将创建的正则表达式编译成一个可供计算机识别和处理的对象。这样可以提高匹配的效率。 4. 使用正则表达式进行匹配:使用编译好的正则表达式对象对目标字符串进行匹配。可以使用匹配函数或方法对字符串进行匹配操作,返回匹配到的结果。 5. 获取匹配结果:匹配函数或方法会返回匹配的结果,可以根据需要进行进一步的处理和操作。可以获取匹配的子串、位置或其他相关信息。 6. 重复匹配:正则表达式通常可以进行多次重复匹配。可以使用循环等方式对目标字符串进行重复匹配,找到所有符合要求的子串。 7. 替换和修改:正则表达式还可以用来进行替换和修改操作。可以使用替换函数或方法将匹配到的内容进行替换,或者通过修改正则表达式的模式来达到修改字符串的目的。 需要注意的是,正则表达式的语法和使用方法会因不同的编程语言而有所差异,具体使用时需要参考相应的文档和教程。同时,正则表达式的匹配和使用也需要一定的经验和技巧,对于复杂的匹配需要深入学习和实践。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值