こんにちは。「Javaを復習する初心者」です。
今回はString#split()メソッドを使いました。このメソッドは文字列を分割するメソッドです。
扱う文字列
今回扱う文字列は以下です。
- java-beginner.com x.xx.xxx.xxxx – – [27/Jul/2016:23:48:20 +0900]
これはサーバのアクセスログの先頭部分の以下を抜粋したものです。
- アクセス先ドメイン名
- アクセス元のホスト名もしくはIPアドレス
- クライアント側のユーザ名(通常は空欄)
- 認証を行った際のユーザ名(通常は空欄)
- アクセス日時
これを半角空白で分割しようとした場合、Stringクラスに以下のメソッドが用意されてます。
- String[] split(String regex)
- String[] split(String regex, int limit)
空白で分割
空白で分割しようと思ったので以下のプログラムが思いつきました。仮引数の「String regex」は正規表現なのですが、単純に「” “」にしました。
ソースコード
package stringTest;
public class HelloSplit {
public static void main(String[] args) {
String log = "java-beginner.com x.xx.xxx.xxxx - - [27/Jul/2016:23:48:20 +0900]";
for (String s : log.split(" ")) {
System.out.println(s);
}
}
}
結果
java-beginner.com
x.xx.xxx.xxxx
-
-
[27/Jul/2016:23:48:20
+0900]
拡張for文のところで「log.split(” “)」で分割をしてます。しかし、結果は最後の部分で不具合が発生しました。よく見ると時刻の箇所で「 +0900」に半角空白があります。
これを改善するための暫定的な方法は「log.split(” “, 5)」として、分割数を制限する方法です。しかし、これは今回の抜粋ログだから使える方法なので、もっと汎用的に正規表現を使いましょう。
汎用的な正規表現
そこで使ったのが「log.split(“(?!(\\s\\+))\\s”)」です。正規表現の部分はJavaファイルに記述するので円マークを使ってエスケープしてますが、正規表現の「(?!(\s\+))\s」です。正規表現については全然詳しくないのですが、「?!」でパターンを否定できるようです。なので「 +」以外で「 」を分割文字列として扱うことになります。結果は以下のようになりました。
ソースコード
package stringTest;
public class HelloSplitRegex {
public static void main(String[] args) {
String log = "java-beginner.com x.xx.xxx.xxxx - - [27/Jul/2016:23:48:20 +0900]";
String regex = "(?!(\\s\\+))\\s";
System.out.println("regex: " + regex);
for (String s : log.split(regex)) {
System.out.println(s);
}
}
}
結果
regex: (?!(\s\+))\s
java-beginner.com
x.xx.xxx.xxxx
-
-
[27/Jul/2016:23:48:20 +0900]
期待通り、時刻の箇所は分割されずに済みました。