2009-07-05 57 views
127

我正在经过一些关于如何在ANSI C中使用正则表达式的简单示例和最佳实践。man regex.h没有提供太多帮助。C中的正则表达式:例子?

+5

ANSI C中没有内置的正则表达式支持。您使用的是哪种正则表达式库? – Joe 2009-07-06 01:59:55

+5

[Rob Pike](http://en.wikipedia.org/wiki/Rob_Pike)写了一个小型的正则表达式字符串搜索函数,该函数接受了一本非常有用的正则表达式子集,他编写了“编程实践”一书,他和[Brian Kernighan ](http://en.wikipedia.org/wiki/Brian_Kernighan)共同撰写。见Kernighan博士的这个讨论,一个正则表达式匹配器http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html – 2014-12-14 23:18:25

回答

167

正则表达式实际上不是ANSI C的一部分。听起来好像你可能会谈论POSIX正则表达式库,它带有大多数(所有?)* nixes。这里是(基于this c)中使用POSIX正则表达式的例子:

#include <regex.h>   
regex_t regex; 
int reti; 
char msgbuf[100]; 

/* Compile regular expression */ 
reti = regcomp(&regex, "^a[[:alnum:]]", 0); 
if (reti) { 
    fprintf(stderr, "Could not compile regex\n"); 
    exit(1); 
} 

/* Execute regular expression */ 
reti = regexec(&regex, "abc", 0, NULL, 0); 
if (!reti) { 
    puts("Match"); 
} 
else if (reti == REG_NOMATCH) { 
    puts("No match"); 
} 
else { 
    regerror(reti, &regex, msgbuf, sizeof(msgbuf)); 
    fprintf(stderr, "Regex match failed: %s\n", msgbuf); 
    exit(1); 
} 

/* Free memory allocated to the pattern buffer by regcomp() */ 
regfree(&regex); 

或者,你可能想看看PCRE,在C. Perl的语法Perl兼容的正则表达式库是相当多的是在Java,Python和许多其他语言中使用相同的语法。该POSIX语法使用grepsedvi语法等

9

它可能不是你想要的,但像re2c的工具可以编译POSIX(-ish)正则表达式来ANSI C.它用作为替代对于lex,但是如果你真的需要这种方法,你可以牺牲最后一点速度的灵活性和可读性。

3

man regex.h报告没有用于regex.h的手动输入,但man 3 regex为您提供了一个解释用于模式匹配的POSIX函数的页面。

The GNU C Library: Regular Expression Matching中描述了相同的功能,其中解释了GNU C库支持POSIX.2接口以及GNU C库多年以来的接口。

例如,对于一个假想的程序,它作为参数传递的字符串匹配的模式作为第一个参数传递打印,你可以使用类似的代码下列之一:

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

void print_regerror (int errcode, size_t length, regex_t *compiled); 

int 
main (int argc, char *argv[]) 
{ 
    regex_t regex; 
    int result; 

    if (argc < 3) 
    { 
     // The number of passed arguments is lower than the number of 
     // expected arguments. 
     fputs ("Missing command line arguments\n", stderr); 
     return EXIT_FAILURE; 
    } 

    result = regcomp (&regex, argv[1], REG_EXTENDED); 
    if (result) 
    { 
     // Any value different from 0 means it was not possible to 
     // compile the regular expression, either for memory problems 
     // or problems with the regular expression syntax. 
     if (result == REG_ESPACE) 
     fprintf (stderr, "%s\n", strerror(ENOMEM)); 
     else 
     fputs ("Syntax error in the regular expression passed as first argument\n", stderr); 
     return EXIT_FAILURE;    
    } 
    for (int i = 2; i < argc; i++) 
    { 
     result = regexec (&regex, argv[i], 0, NULL, 0); 
     if (!result) 
     { 
      printf ("'%s' matches the regular expression\n", argv[i]); 
     } 
     else if (result == REG_NOMATCH) 
     { 
      printf ("'%s' doesn't the regular expression\n", argv[i]); 
     } 
     else 
     { 
      // The function returned an error; print the string 
      // describing it. 
      // Get the size of the buffer required for the error message. 
      size_t length = regerror (result, &regex, NULL, 0); 
      print_regerror (result, length, &regex);  
      return EXIT_FAILURE; 
     } 
    } 

    /* Free the memory allocated from regcomp(). */ 
    regfree (&regex); 
    return EXIT_SUCCESS; 
} 

void 
print_regerror (int errcode, size_t length, regex_t *compiled) 
{ 
    char buffer[length]; 
    (void) regerror (errcode, compiled, buffer, length); 
    fprintf(stderr, "Regex match failed: %s\n", buffer); 
} 

regcomp()的最后一个参数至少需要REG_EXTENDED,否则功能将使用basic regular expressions,这意味着(例如)您需要使用a\{3\}而不是extended regular expressions中使用的a{3},这可能是您期望使用的。

POSIX.2还有另一个通配符匹配功能:fnmatch()。它不允许编译正则表达式,也不允许与子表达式匹配的子字符串,但是它非常具体地用于检查文件名与通配符匹配的时间(例如,它使用FNM_PATHNAME标志)。