特定のグループが一致しない場合でも一致するには、それらをオプションにする必要があります。
次に、このMatcher#find()
メソッドを使用しMatcher#group(x)
てグループにアクセスします (0 は完全な一致であるため、1 から開始します)。
例:
String msg = "GET HTTP 200 OK"; //resource and protocol version are left out by purpose
Pattern pattern = Pattern.compile("(GET|get)?\\s(/[^\\s]*)?\\s(HTTP|http)?(/1\\.0)?");
Matcher matcher = pattern.matcher( msg );
while ( matcher.find() )
{
System.out.println(matcher.group( 1 )); //prints GET
System.out.println(matcher.group( 2 )); //prints null since there's no resource
System.out.println(matcher.group( 3 )); //prints HTTP
System.out.println(matcher.group( 4 )); //prints null since there's no version string
}
(/.*)
補足として、2 番目のグループは最初のスラッシュの後の任意のものに貪欲に一致するため、表現を少し調整する必要がありました。とはいえ、まだ完璧にはほど遠いです。
2 番目のアプローチは、複数の式/パターンを適用し、それらをマッチャーに次々と適用することです。
例:
Pattern methodPattern = Pattern.compile("GET|get");
Matcher matcher = methodPattern.matcher( msg );
if ( matcher.find() )
{
System.out.println("method: " + matcher.group());
}
if ( matcher.usePattern( Pattern.compile("\\s/([^\\s]*)") ).find() )
{
System.out.println("resource: " + matcher.group(1));
}
if ( matcher.usePattern( Pattern.compile("HTTP|http") ).find() )
{
System.out.println("protocol: " + matcher.group());
}
if ( matcher.usePattern( Pattern.compile("/(\\d\\.\\d)") ).find() )
{
System.out.println("version: " + matcher.group(1));
}
これは、マッチャーの読み取り位置が一致後の位置に設定され、後続の呼び出しfind()
がそこから開始されるという事実を利用しています。パターンが一致しない場合、位置は変更されません。
したがって、パターンは順番に適用する必要がありますが、オプションです。