1

次の形式の文字列を一致させようとしています。

S->A  
S->AbCd  
S->A|b|C|d  
S->Ab|B|cde|dB 

つまり、左端には、大文字のラテンアルファベット記号が1つだけあり、その後に「->」リテラルが続きます。その後、リテラルは、大文字/非大文字のラテンアルファベット記号またはそのような記号の連結の後に続きます。これらの記号の後には、「|」で区切られた記号のグループも続く場合があります。シンボル。
また、文字列全体がこの形式に準拠しているかどうかを確認するだけでなく、左端の大文字記号と「->」リテラルの後のすべての記号グループの両方をキャプチャできるようにします。これまでのところ、私はこの正規表現を思いついた:

([A-Z]{1})->([a-zA-Z]+)(?:(?:\|)([a-zA-Z]+))*

たとえば、次の文字列に対してテストすると、次のようになります。

S->Ab|B|c|d

次の結果が得られます(RegexBuddyでテストを行いました)。

Match 1:    S->Ab|B|c|d
Group 1:    S
Group 2:    Ab
Group 3:    d

良いことは、私の正規表現が文字列全体と一致することです(これは正しいです)。ただし、問題は明らかです。私の正規表現は、「->」リテラルの後の最初と最後のシンボルグループのみをキャプチャします。なんで?正規表現の私の理解に基づいて、表現のこの部分

(?:(?:\|)([a-zA-Z]+))*

すべての区切られたシンボルグループと一致する必要があります。これは、 「キャプチャグループの繰り返しと繰り返しグループのキャプチャ」の記事で説明されている内容に関連していると思います。正規表現を少しいじってみましたが、満足のいく結果が得られませんでした。助言がありますか?

4

4 に答える 4

2

正規表現にはキャプチャ括弧のペアが3つしかないため、3つのグループしか取得できません(これは、「繰り返しグループのキャプチャとキャプチャグループの繰り返し」に関連しています)。グループの数は常に固定されています。

明確にするためにPerlのような間隔を使用m//xして物事を分割します。

([a-zA-Z]{1})  ->  ([a-zA-Z]+)  (?: (?:\|) ([a-zA-Z]+) )*
^-----------^      ^---------^             ^---------^

3つのキャプチャパーツが表示されます。他の括弧はキャプチャされていません。明らかに、後続のグループ全体をキャプチャできます。

    ([a-zA-Z]{1})  ->  ([a-zA-Z]+)  ( (?:\|) (?:[a-zA-Z]+) )*

splitただし、サブフィールドを取得するには、おそらく操作を使用して、後続グループを後処理する必要があります。

于 2012-04-25T06:16:53.280 に答える
1

構文(?:...)は、非キャプチャグループを意味します。

キャプチャグループが必要な場合は、代わりに使用する必要があります(...)

これを試して:

([a-zA-Z]{1})->([a-zA-Z]+)(\|[a-zA-Z]+)*

各要素を個別に使用する場合は、区切り文字で分割できます。

于 2012-04-25T06:16:44.093 に答える
1

はい、あなたの問題は、あなたが捕獲グループを繰り返しているということです。

(?:(?:\|)([a-zA-Z]+))*
         ^^^^^^^^^^^
          third group

そうです、この部分全体がすべての繰り返しグループと一致しており、それらの各一致はに格納され$3ているため、すべての一致が行われた後、このグループの最後の一致のみが表示dされます。これは例に含まれています。

このように繰り返しグループをキャプチャできます

([a-zA-Z]{1})->([a-zA-Z]+)((?:(?:\|)[a-zA-Z]+)*)

その場合、結果は次のようになります

Match 1:    S->Ab|B|c|d
Group 1:    S
Group 2:    Ab
Group 3:    |B|c|d
于 2012-04-25T06:20:23.437 に答える
1

キャプチャグループ3はすべてのシンボル([a-zA-Z]+)に一致します。最初に「B」に一致し、次に正規表現が進むにつれて「c」に|置き換えられ、最後に結果のように「d」に置き換えられます。

于 2012-04-25T06:21:22.317 に答える