2017-02-09 4 views
0

正規表現パターンは、次のことを一致している必要がありますC - regexecはNOMATCHを返します。

abc_xyz_0 
abc_1025_01.29.00_xyz_0 
abc_0302_42.01.00_xyz_0 

(ABCとXYZの間の数字は重要ではいけない)

だから、私はパース:

(abc_(\w+\.\d+\.\w+)?xyz_0) 

マイコード:

regex_t r; 
unsigned int maxGroups = 3; 
regmatch_t groupArray[maxGroups]; 
char * to_match = "abc_0302_02.01.00_xyz_18 abc_0302_02.01.00_xyz_16 abc_0302_02.01.00_xyz_14 abc_0302_02.01.00_xyz_0 abc_0302_02.01.00_xyz_10 abc_0302_02.01.00_xyz_2" 

if (0 != regcomp(&r, "(abc_(\\w+\\.\\d+\\.\\w+)?xyz_0)", REG_EXTENDED)) 
{ 
    //this does NOT get hit 
    printf("regcomp failed") 
} 
else if(regexec(r, to_match, maxGroups, groupArray, REG_EXTENDED) == 0) 
{ *never gets here* } 
else 
{ printf("regexec returned non-zero(No Matches)\n"); } 

regfree(&r); 

だから私のg私は間違った正規表現を持っています(上で定義した私のケースではうまくいきます - regexpal.comを使って確認しています)か、何か紛失していますか?

いずれにしても、私は近いとわかっていて、助けていただければ幸いです。

+0

これは 'abc(?:_ \ d + _ \ d +)?_ xyz_0'です。 – sln

+0

@sln助けてくれて本当に感謝しています。 "?:"を追加すると、regcompが失敗します。 これは私のためには機能しませんでした。 (abc _(\?:\\ w + \\。\\ d + \\。\\ w +)?xyz_0) –

答えて

1

質問にコピーしたコードにいくつかのタイプミスがあります(下記参照)。REG_EXTENDEDregcompにのみ渡す必要があります。フラグregexecのみがREG_NOTBOLREG_NOTEOLと認識されます。

しかし、問題は、Gnuの実装を含むPosixの正規表現では、非標準のエスケープシーケンス\dが実装されていないことです。 regex(7) manpageに示すように、パターンは含めることができます「?^ [$()| * + {\」

を「\」の文字のいずれかに続いて(通常の扱いでの文字にマッチ)、

又は

'\'( '\' 存在していなかったかのように、通常の文字とし、その文字にマッチする)、任意の他の文字が続く

\の唯一の効果は、いずれの場合でも、次の文字を通常の文字として一致させることです。 regcompのGnuの実装では、文字クラスとして\wが認識されますが、その動作はPosixでは必須ではなく、他の実装ではそうでないかもしれません。 (これも文書化されていないので、常に機能するとは限りません)。\dは認識されません。あなたがのPosix正規表現を使用している場合

、あなたは、POSIX標準の文字クラスを使用する必要がありますので、正規表現文字列は次のようになります。

"(abc_([[:alnum:]_]+\\.[[:digit:]]+\\.[[:alnum:]_]+)?xyz_0)" 

はあなたが正規表現のmanページにPosixの名前付き文字クラスのリストを見つけることができます前のリンク(またはあなたが強く推奨されている標準ライブラリのマニュアルを参照して、インストールしていると仮定しman 7 regexを入力して。)

私はコールに&rchar * to_match =...の終わりにセミコロンを追加してrを変更した後、あなたのコードでこれを検証しますにregexec

驚くほど、オンラインの正規表現リソースがPosixの正規表現仕様を実装していることに注意してください。たとえば、http://regexpal.comは、PCREスタイルとJavascriptスタイルの正規表現のオプションのみを提供します。


あなたがregexecを呼び出すたびに、あなたはman 7 regexで説明した固定アルゴリズムに従って、あなたはそれに渡す文字列の最初の試合を取得:

REが一致する可能性がある場合には、より の指定された文字列の1つの部分文字列よりも、REは文字列の中で最も早く始まるものと一致します。 REが、その時点から始まる複数の部分文字列と一致する可能性がある場合は、 が最長一致になります。サブ式はまた、可能な限り長く続く という一致を条件として、最も遅い サブストリングと一致します。サブタイプは、後で開始するサブタイプより優先してサブタイプが で始まります。上位レベルの サブ式は、下位レベルのコンポーネント サブ式よりも優先されます。

同じ文字列内のパターンの複数のインスタンスを検索する場合は、regexecをループで呼び出す必要があります。ループを通過するたびに、それ以上の一致が報告されなくなるまで前の一致(つまり、string + matches[0].rm_eo)から最初に一致しなかったバイトのアドレスが返されます。あなたの試合に^のアンカーを頼っている場合は、regexecへの各呼び出しにREG_NOTBOLフラグの正しい値を渡す必要があります。

+0

ありがとうございました。フォローアップの質問:キャプチャしていないグループが必要な場合は、どうすればよいでしょうか?私は "regexec()"を実行した後、私は1つだけのキャプチャグループを必要とし、複数ではありません。その理由は、私がabc _ #### _ ##。##。## _ xyz_0の複数のインスタンスを持っている場合、私はそのユーザーのオプションを提供したいのです。 abc_xyz_0 | abc _ [[alnum:] _] + \。[[:digit:]] + \ [[:alnum:] _] + xyz_0 非キャプチャグループ?:は認識されず、マニュアルページに何も表示されません。 –

+0

提案された正規表現の文字列(バッファ内に1つの一致がある)で実行すると、 "abc _ #### _ ##。##。## _ xyz_0"と "#### _ ##。## 。## _ "。 2+個のグループを受信して​​も問題ありませんが、バッファに2個以上の一致がある場合に限ります。 また、文法エラーのために申し訳ありませんが、正規表現/バッファは質問よりもはるかに複雑でしたので、関数呼び出しなどを削除してコードを単純化して、平均的な読者が理解できるようにしました。 –

+0

@GraysonHenry: 'regexec'を呼び出すたびに、ちょうど1つのマッチが返され、そのマッチのキャプチャが埋められます。これが(ほとんどの)正規表現ライブラリが動作する方法です。同じマッチ*から複数のキャプチャをしたいので、複数のマッチグループを指定します*。 Posixの正規表現はグループをキャプチャしない '(?:...)'構文をサポートしていませんが、キャプチャがかなり安価であることもあります。気にしないキャプチャは無視してください。 regexecにキャプチャしたいグループの数を伝えている限り、マッチ配列に正規表現内のすべてのキャプチャのためのスペースを与える必要はありません。 – rici

関連する問題