Regular Expressions
グループのキャプチャ
サーチ…
基本キャプチャ・グループ
グループは、カッコ()
囲まれた正規表現のセクションです。これは一般に「サブ式」と呼ばれ、2つの目的を果たします。
- これは、サブ表現をアトミックにします。つまり、全体として一致するか、失敗するか、繰り返されます。
- 一致したテキストの部分は、式の残りの部分とプログラムの残りの部分でアクセス可能です。
グループは1から始まる正規表現エンジンで番号が付けられます。伝統的に最大グループ数は9ですが、現代の正規表現の多くはグループ数を増やすことができます。グループ0はパターン全体と常に一致しますが、大括弧で正規表現全体を囲むのと同じ方法です。
グループが前後に配置されているか、ネストされているかにかかわらず、括弧のついた序数は増加します。
foo(bar(baz)?) (qux)+|(bla)
1 2 3 4
グループとその番号
式が全体的な一致を達成した後、特定のグループが何かにマッチするかどうかに関係なく、そのグループのすべてが使用されます。
グループは(baz)?
ようにオプションにすることができます(baz)?
上記の(bla)
ように、マッチの使用されなかった式の別の部分にも使用できます。これらの場合、一致しないグループには情報が含まれません。
もし(qux)+
ようにグループの後に量子を置くと、式の全体的なグループ数は同じままになります。グループが複数回一致する場合、そのグループのコンテンツは最後の一致の発生となります。しかし、現代の正規表現フレーバは、すべてのサブマッチの発生にアクセスすることを可能にします。
このようなログエントリの日付とエラーレベルを取得する場合は、次のようにします。
2012-06-06 12:12.014 ERROR: Failed to connect to remote end
次のようなものを使うことができます:
^(\d{4}-\d{2}-\d{2}) \d{2}:\d{2}.\d{3} (\w*): .*$
これにより、キャプチャグループ1としてログエントリ2012-06-06
日付が抽出され、キャプチャグループ2としてエラーレベルERROR
が抽出されます。
後方参照および非捕捉グループ
グループは「番号が付けられている」ため、一部のエンジンでは、グループが以前に一致したものとのマッチングもサポートされます。
2つの長さが3の文字列が$
割られたものとマッチすると仮定した場合、次のようになります。
(.{3})\$\1
これは、次の文字列のいずれかと一致します。
"abc$abc"
"a b$a b"
"af $af "
" $ "
グループにエンジンの番号を付けない場合は、非キャプチャと宣言することができます。非キャプチャグループは次のようになります。
(?:)
グループは「アトム」としても使用できるため、特定のパターンを何回でも繰り返すことが特に便利です。検討してください:
(\d{4}(?:-\d{2}){2} \d{2}:\d{2}.\d{3}) (.*)[\r\n]+\1 \2
これは、同じタイムスタンプと同じエントリを持つ隣接行の2つのロギングエントリに一致します。
名前付きキャプチャ・グループ
一部の正規表現のフレーバでは、 名前付きのキャプチャグループを使用できます 。数値インデックスの代わりに、これらのグループを後続のコード、すなわち後方参照、置換パターン、およびプログラムの次の行で名前で参照できます。
数値インデックスは、式内のグループの数または配置が変化すると変化するため、比較するとより脆弱になります。
たとえば、一重または二重引用符( ['"]
)で囲まれた単語( \w+
)を照合するには、次のように使用します。
(?<quote>['"])\w+\k{quote}
これは次のものと同等です:
(['"])\w+\1
このような単純な状況では、通常の番号を付されたキャプチャグループには、何らかの欠点がありません。
より複雑な状況では、名前付きグループを使用すると、式の構造が読者にとってより明らかになり、保守性が向上します。
ログファイルの解析は、グループ名を使用するより複雑な状況の例です。これはApache Common Log Format (CLF)です。
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
次の式は、パーツを名前付きグループに取り込みます。
(?<ip>\S+) (?<logname>\S+) (?<user>\S+) (?<time>\[[^]]+\]) (?<request>"[^"]+") (?<status>\S+) (?<bytes>\S+)
構文はフレーバーに依存しますが、一般的なものは次のとおりです。
-
(?<name>...)
-
(?'name'...)
-
(?P<name>...)
後方参照:
-
\k<name>
-
\k{name}
-
\k'name'
-
\g{name}
-
(?P=name)
.NETフレーバでは、複数のグループに同じ名前を共有させることができます 。それらはキャプチャスタックを使用します 。
PCREでは、 (?J)
修飾子( PCRE_DUPNAMES
)を使用するか、ブランチリセットグループ(?|)
を使用して明示的に有効にする必要があります。ただし、最後に取得した値だけにアクセスできます。
(?J)(?<a>...)(?<a>...)
(?|(?<a>...)|(?<a>...))