val p : Regex = ".*no=([0-9]+),name=(.*)".r; val values = List( "no=10,name=ten", "no=11,name=eleven", "no=20,name=twelve" ); for (value <- values ) { value match { case p("10", v) => println("name for 10: " + v) case p("11", v) => println("name for 11: " + v) case p(n, v) => println("name, value= " + (n,v)) } }
name for 10: ten name for 11: eleven name, value= (20,twelve)
String#r メソッドで scala.util.matching.Regex オブジェクトを作ることができる。
match ... case 文の case 句で、正規表現中のグループに対する値や変数を指定しておくことで、 比較対象の文字列とマッチさせることができる。
上の例の最初と2つめの case 句では、第一グループに値を指定してマッチした対象の第2グループの値を変数に入れて取り出す。
3番目の case 句では1番目、2番目の case 句でマッチしなかった対象に対して両グループの値を取り出している。
この動作の仕組みを調べてみよう。
Scala の Regex は普通こんな感じで使う。
val p : Regex = """.*no=([0-9]+),name=(.*)""".r; val s = "no=10,name=ten"; val m : Regex.Match = p.findFirstMatchIn(s).get; println("no: " + m.group(1)) println("name: " + m.group(2))
no: 10 name: ten
Regex には メンバーメソッドに抽出子 unapplySeq があって文字列を渡すことができる。
val p : Regex = """.*no=([0-9]+),name=(.*)""".r; val s = "no=10,name=ten"; println(p.unapplySeq(s));
Some(List(10, ten))
正規表現を使った match...case 文ではこの抽出子を使ってグループの値を取り出して マッチを行っているものと思う。
Regex の派生クラスを作って、unapplySeq を override して実験。
val p : Regex = new Regex2(""".*no=([0-9]+),name=(.*)"""); val value = "no=10,name=ten"; value match { case p("10", v) => println("name for 10: " + v) case p(n, v) => println("name, value= " + (n,v)) } ... private class Regex2(regex: String) extends Regex(regex) { override def unapplySeq(target: Any): Option[List[String]] = { println("Regex2 unapplySeq called."); return super.unapplySeq(target); } }
Regex2 unapplySeq called. name for 10: ten
確かに Regex の unapplySeq が実行されていることが分かった。
0 件のコメント:
コメントを投稿