java.util.Scannerクラス
Java 2 SE 5.0で、java.util.Scannerクラスが追加された。
(もともとは、java.lang.Readableインタフェースを見ていたんだけど、このインタフェースを使用するクラスがScannerクラスしかなくて、見てみたら‥という(謎))
A simple text scanner which can parse primitive types and strings using regular expressions.
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods.
で、見ていたら、「AWKとかと同じことができるんでは?」と思い立ち、ちょっとサンプルを書いてみた。
まず、シンプルなAWKのプログラム。
BEGIN { FS=","; } { printf("[%s][%s][%s]\n", $1, $2, $3); }
これに入力として
1,1.1,1.11 2,2.2,2.22 3,3.3,3.33
のようなものを与えると、
[1][1.1][1.11] [2][2.2][2.22] [3][3.3][3.33]
という出力を生成する。
これと同じ処理をScannerクラスを使って書いてみる。
import java.io.StringReader; import java.util.Scanner; import java.util.regex.MatchResult; public class Main { /** * @param args */ public static void main(String[] args) { String data = "1,1.1,1.11\n2,2.2,2.22\n3,3.3,3.33\n"; Scanner scanner = new Scanner(new StringReader(data)); String pattern = "([^,\n]*),([^,\n]*),([^,\n]*)"; // String pattern = "(\\d+),([\\d]+[.][\\d]+),([\\d]+[.][\\d]+)"; while (scanner.findInLine(pattern) != null) { MatchResult match = scanner.match(); String s1 = (match.groupCount() > 0 ? match.group(1) : null); String s2 = (match.groupCount() > 1 ? match.group(2) : null); String s3 = (match.groupCount() > 2 ? match.group(3) : null); System.out.printf("[%s][%s][%s]\n", s1, s2, s3); } } }
これで、結果はAWKの場合と同じとなる。
コメントアウトしてある方のpatternを使用すると、"\\d"がdigitを表すので、1つ目が整数値、2つ目と3つ目が小数値を表す文字列として解析される。こういった正規表現を用いた解析も可能。
とりあえず、サンプルでは行あたりのトークン数は固定であると仮定しているが、match.groupCount()をちゃんと使えば行ごとにトークン数が異なっても使えるので、コマンドラインツールを作るときには役に立つかも。