次の入力があるとしましょう。
<amy>
(bob)
<carol)
(dean>
次の正規表現もあります。
<(\w+)>|\((\w+)\)
これで、2つの一致が得られます(rubular.comで見られるように):
<amy>
一致し、\1
キャプチャしamy
、\2
失敗します(bob)
一致し、\2
キャプチャしbob
、\1
失敗します
この正規表現は、私たちが望むことのほとんどを実行します。
- 開閉ブラケットと適切に一致します(つまり、混合なし)
- 興味のある部分をキャプチャします
ただし、いくつかの欠点があります。
- キャプチャパターン(つまり「メイン」部分)が繰り返されます
- この場合のみ
\w+
ですが、一般的に言えば、これは非常に複雑になる可能性があります。- 後方参照が含まれる場合は、代替ごとに番号を付け直す必要があります。
- 繰り返しはメンテナンスを悪夢にします!(変更された場合はどうなりますか?)
- この場合のみ
- グループは本質的に複製されます
- どの代替一致に応じて、異なるグループにクエリを実行する必要があります
- それは唯一
\1
または\2
この場合ですが、一般的に「メイン」部分は独自のキャプチャグループを持つことができます!
- それは唯一
- これは不便であるだけでなく、これが実行できない場合もあります(たとえば、1つのグループのみのクエリに制限されているカスタム正規表現フレームワークを使用している場合)。
- どの代替一致に応じて、異なるグループにクエリを実行する必要があります
{...}
、[...]
なども一致させたい場合、状況は急速に悪化します。
したがって、問題は明らかです。「メイン」パターンを繰り返さずにこれを行うにはどうすればよいでしょうか。
注:ほとんどの場合、私は
java.util.regex
フレーバーに興味がありますが、他のフレーバーも歓迎します。
付録
このセクションには何も新しいことはありません。上記の問題を例で示しているだけです。
上記の例を次のステップに移しましょう。これらを一致させたいと思います。
<amy=amy>
(bob=bob)
[carol=carol]
しかし、これらではありません:
<amy=amy) # non-matching bracket
<amy=bob> # left hand side not equal to right hand side
別の手法を使用すると、次のように機能します(rubular.comで見られるように)。
<((\w+)=\2)>|\(((\w+)=\4)\)|\[((\w+)=\6)\]
上で説明したように:
- メインパターンを単純に繰り返すことはできません。後方参照の番号を付け直す必要があります
- 繰り返しは、それが変更された場合のメンテナンスの悪夢も意味します
- どの代替一致に応じて、、、またはのいずれかをクエリする必要が
\1 \2
あり\3 \4
ます\5 \6