6

A0123456E0123456、またはなどの形式の文字列に一致させたいIN:A0123456Q。もともとこの正規表現を作成した

^(IN:)?[AE][0-9]{7}Q?$

IN:E012346しかし、最後に なしで一致していQました。だから私はこの正規表現を作成しました

(^IN:[AE][0-9]{7}Q$)|(^[AE][0-9]{7}$)

この正規表現を短くして、両方が必要であり、どちらも存在しない場合は不要にする方法はありIN:ますQか?

編集: 正規表現は Ruby で使用されます。

編集 2: 正規表現を変更して、間違った文字列に一致していたことを反映させましたIN:A0123456

編集 3: 以下の両方の回答は有効ですがRuby 2.0、アプリケーションを変更し、Ruby フレーバーの部分式呼び出しを使用したくない場合に使用できる正規表現を使用していて、好むため、mattの回答を受け入れることにしました。

4

2 に答える 2

5

2 番目の正規表現には問題があります。

^(IN:[AE][0-9]{7}Q)|([AE][0-9]{7})$

|連結よりも優先順位が低いため、正規表現は次のように解析されます。

^(IN:[AE][0-9]{7}Q)        # Starts with (IN:[AE][0-9]{7}Q)
|                          # OR
([AE][0-9]{7})$            # Ends with ([AE][0-9]{7})

この問題を解決するには、非キャプチャ グループを使用します。

^(?:(IN:[AE][0-9]{7}Q)|([AE][0-9]{7}))$

入力文字列が特定の形式で開始または終了するだけでなく、どちらの形式にも一致することを確認します (これは明らかに正しくありません)。


正規表現の短縮については、必要に応じて に置き換え[0-9]\dもかまいませんが、そのままで結構です。

Ruby のデフォルト サポート レベル内で正規表現を短縮する方法は他にないと思います。

サブルーチン呼び出し

参考までに、Perl/PCRE では、サブルーチン callで短縮できます:

^(?:([AE][0-9]{7})|(IN:(?1)Q))$

(?1)は、最初のキャプチャ グループによって定義されたパターンを参照し[AE][0-9]{7}ます。正規表現は事実上同じですが、短く見えるだけです。この入力付きのデモIN:E0123463Qは、グループ 2 によってキャプチャされたテキスト全体を示しています (グループ 1 ではキャプチャされたテキストはありません)。


Ruby には、構文がわずかに異なる、同様の概念の 部分式呼び出しが存在します。Ruby は\g<name>or\g<number>を使用して、パターンを再利用したいキャプチャ グループを参照します。

^(?:([AE][0-9]{7})|(IN:\g<1>Q))$

Ruby 1.9.7 でのrubularのテスト ケースは、 input に対して、グループ 1 の一致として、グループ 2 の一致としてIN:E0123463Q返されます。E0123463IN:E0123463Q

Ruby の (1.9.7) 実装は、グループ 1 がマッチングに直接関与していない場合でも、グループ 1 のキャプチャされたテキストを記録するようです。PCRE では、サブルーチン呼び出しはテキストをキャプチャしません。

条件付き正規表現

特定のキャプチャ グループが何かに一致するかどうかを確認できる条件付き正規表現もあります。詳細については、マットの回答を確認してください。

于 2013-09-11T22:48:48.883 に答える