2009-07-05 58 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標誌)。