2009-07-05 17 views
127

ANSI Cで正規表現を使用する方法の簡単な例とベストプラクティスの後には、man regex.hはあまり役に立ちません。Cの正規表現:例?

+5

ANSI Cにregexの組み込みサポートはありません。どの正規表現ライブラリを使用していますか? – Joe

+5

[Rob Pike](http://en.wikipedia.org/wiki/Rob_Pike)は、彼と[Brian Kernighanの著書「The Practice of Programming」の正規表現の非常に有用なサブセットを受け入れる小さな正規表現文字列検索関数を書いた](http://en.wikipedia.org/wiki/Brian_Kernighan)共著。このディスカッション、正規表現のMatcher、Kernighan博士の記事を参照してください。http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html –

答えて

167

正規表現は実際にはANSI Cの一部ではありません。ほとんどの(すべて?)* nixesに付属しているPOSIX正規表現ライブラリについて話しているようです。ここで(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構文はなどgrepで使用される構文、sedvi

+4

私は第2のPCREの依存関係を避ける必要がない限り、いくつかの優れた構文拡張があり、非常に安定しています。少なくとも古いバージョンのLinuxでは、特定の入力文字列や特定の正規表現が "ほぼ"一致するか、多くの特殊文字が含まれていると、 "組み込みの"正規表現ライブラリはクラッシュするのが難しくありません。 – bdk

+0

@Laurence意味regcompに0を渡す? regcompは、4つの異なるモードを表すために4つの整数値1,2,4,8を取るだけです。 – lixiang

+2

@lixiang 'regcomp'の最後のパラメータ、' cflags'はビットマスクです。 http://pubs.opengroup.org/onlinepubs/009695399/functions/regcompから。html: "cflags引数は、以下のフラグのゼロ以上のビット単位のORです..."。もしあなたがORを0にすると、0になるでしょう。私は、 'regcomp'のLinuxマンページは、" cflagsがビット単位であるかもしれない、あるいは以下のうちの1つ以上であるかもしれない "と言います。 –

9

であるそれはあなたが望むものはおそらくありませんが、re2cのようなツールは、それが代替として書かれているANSI CにPOSIX(-ish)正規表現をコンパイルすることができますlexの場合、このアプローチでは、本当に必要な場合は、速度の最終段階で柔軟性と読みやすさを犠牲にすることができます。

3

man regex.hレポートregex.hのマニュアルエントリはありませんが、man 3 regexは、パターンマッチングのためのPOSIX関数を説明するページを提供します。

同じ機能がThe GNU C Library: Regular Expression Matchingに記載されています。ここでは、GNU CライブラリがPOSIX.2インターフェイスとGNU Cライブラリの長年の間に両方をサポートしていることが説明されています。例えば

、引数は最初の引数として渡されたパターンに一致するとして、あなたは次のようなコードを使用することができ渡された文字列のプリントがどの仮想的なプログラムのために:regcomp()

#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); 
} 

最後の引数少なくともREG_EXTENDEDである必要があります。または、関数はの代わりにa\{3\}extended regular expressions)を使用する必要があります(おそらく使用すると思われる)。

POSIX.2には、ワイルドカード照合のための別の機能があります。fnmatch()。正規表現をコンパイルすることやサブ表現に一致する部分文字列を取得することはできませんが、ファイル名がワイルドカードと一致するかどうかを確認するために非常に具体的です(例:FNM_PATHNAMEフラグを使用)。