2011-01-05 19 views
2

私はCの正規表現(ちょうど/usr/include/regex.h)に苦しんでいます。Cマッチグループの正規表現


何百もの正規表現があり、そのうちの1つは入力文字列と一致します。 現在、私はこれのように(実際にそれを生成しています)、何百もの中にマッチしていて、マッチングしていないと別のものに行ってしまいます。私がしたいのですがどのような

do { 
    if (regex_match(str, my_regex1) != MY_REGEX_SUCCESS) DO_FAIL; //break 
    ... 
    if (sscanf(str, " %d.%d.%d.%d/%d ", &___ip1, &___ip2, &___ip3, &___ip4, &___pref) != 5) DO_FAIL; //break 
    ... 
} while (0); 

do { 
    if (regex_match(str, my_regex2) != MY_REGEX_SUCCESS) DO_FAIL; //break 
    ... 
    ... 
} while (0); 

do { 
    if (regex_match(str, my_regex3) != MY_REGEX_SUCCESS) DO_FAIL; //break 
    ... 
    ... 
} while (0); 

のようなものです::

const char * match1 = "^([[:space:]]*)([$]([._a-zA-Z0-9-]{0,118})?[._a-zA-Z0-9])([[:space:]]*)$"; 
const char * match2 = "^([[:space:]]*)(target|origin)([[:space:]]*):([[:space:]]*)([$]([._a-zA-Z0-9-]{0,118})?[._a-zA-Z0-9])([[:space:]]*):([[:space:]]*)\\*([[:space:]]*)$"; 
const char * match3 = "^([[:space:]]*)(target|origin)([[:space:]]*):([[:space:]]*)([$]([._a-zA-Z0-9-]{0,118})?[._a-zA-Z0-9])([[:space:]]*)/([[:space:]]*)(([0-2]?[0-9])|(3[0-2]))([[:space:]]*):([[:space:]]*)(([1-9][0-9]{0,3})|([1-5][0-9]{4})|(6[0-4][0-9]{3})|(65[0-4][0-9]{2})|(655[0-2][0-9])|(6553[0-5]))([[:space:]]*)$"; 
char * my_match; 
asprintf(&my_match, "(%s)|(%s)|(%s)", match1, match2, match3); 


int num_gr = give_me_number_of_regex_group(str, my_match) 
switch (num_gr) { 
    ... 
} 

は、どのようにそれを行うためのアイデアを持っていない...

を一つずつ助言がありますか?
ありがとうございます!

+0

デザイン思想に欠陥があると思います。なぜあなたはファイル、単一の列に入力文字列を持つことができません。プログラムに順番にそれらを読み込ませ、文字列と1つずつ比較させますか? – chutsu

+0

また、文字列を比較しているだけの場合は、標準のCライブラリを使用してください。具体的には:strcmp? – chutsu

答えて

4

あなたのregex_matchは、regcompregexecの組み合わせであると仮定します。グループ化を有効にするには、regcompREG_EXTENDEDフラグで呼び出しますが、第3引数にはREG_NOSUBフラグは付けないでください。

regex_t compiled; 
regcomp(&compiled, "(match1)|(match2)|(match3)", REG_EXTENDED); 

次に、グループにスペースを割り当てます。グループ数はcompiled.re_nsubに格納されます。 regexecにこの番号を渡し:

size_t ngroups = compiled.re_nsub + 1; 
regmatch_t *groups = malloc(ngroups * sizeof(regmatch_t)); 
regexec(&compiled, str, ngroups, groups, 0); 

、最初の無効なグループは、そのrm_sorm_eoフィールドの両方に-1の値を有するものである:

size_t nmatched; 
for (nmatched = 0; nmatched < ngroups; nmatched++) 
    if (groups[nmatched].rm_so == (size_t)(-1)) 
     break; 

nmatchedは(括弧内の部分式の数でありますグループ)が一致した。あなた自身のエラーチェックを追加してください。

+0

こんにちは、larsmans、あなたの仮定は正しかった、これは私が必要としていたものです。 サブマッチにグループ化自体が含まれていても動作しますか?私は私の質問をilustrateの下の例を編集しました。もう一度ありがとうございます。 – DinGODzilla

+0

@DinGODzilla:私はUnix REの標準でこれについての発言を見つけることができないので、私の推測は再帰的なグループ化が暗黙的に許可されている(仕様と実装を複雑にすることはできないので)。再帰的なグループ化が機能するかどうか、自分で試してみてください。 –

+0

検索していただきありがとうございます...私はposix RE標準をどこで見つけることができますか? ... "(?:"またはその他の非キャプチャグループが許可されているかどうかを調べるには... – DinGODzilla

0

あなたの正規表現を含む文字列を与え、それらのそれぞれをテストすることができます。

//count is the number of regexps provided 
int give_me_number_of_regex_group(const char *needle,const char** regexps, int count){ 
    for(int i = 0; i < count; ++i){ 
    if(regex_match(needle, regexp[i])){ 
     return i; 
    } 
    } 
    return -1; //didn't match any 
} 

または何かを監督していますか?

0

「私は正規表現の数百人(さんが言わせて)いる...」

あなたは、IPアドレスのクワッド部分を比較しようとしているように見えます。一般的に、正規表現を使用する場合、多くの正規表現を単一のターゲット上で使用し、一致後に停止すると通常は赤いフラグが付きます。

例:最初に正しく一致するグループはどれですか?
target ~'American' , pattern ~ /(Ame)|(Ameri)|(American)/
これには、サブグループに数量詞も含めません。

正規表現の大文字/小文字がデータなどで構成されている場合は、Cの文字列関数を使用してフォームのデータを配列に分割し、次に配列項目を比較する方がよい場合がありますターゲットとCは正規表現よりもはるかに高速です。