Regex#unapplySeq

scala.util.matching.Regex に unapplySeq があるので、match を使うと綺麗にパターンマッチで書ける...? どなたか教えていただけませんか。

http://www.lingr.com/room/scala-ja/archives/2008/05/28#msg-38517596

を受けて、少し実験してみた。

scala> "abc+".r
res0: scala.util.matching.Regex = abc+

scala> res0.unapplySeq("abcc")
res13: Option[List[String]] = Some(List())

scala> res0.unapplySeq("ab")  
res14: Option[List[String]] = None

scala> "(a.c).*".r            
res15: scala.util.matching.Regex = (a.c).*

scala> res15.unapplySeq("a1cdef")
res16: Option[List[String]] = Some(List(a1c))

scala> res15.unapplySeq("asa1cdef")
res17: Option[List[String]] = None

scala> res15.unapplySeq("abcdef")  
res18: Option[List[String]] = Some(List(abc))

scala> "abcdef" match { case res15(x) => x ; case _ => "hoge"}
res19: String = abc

あぁ!なるほど!
ってわけで、サンプルを書いてみる。

val ptn = "[^0-9]*([0-9]+).*".r

val strs = List("hoge", "hoge123", "456piyo", "hoge789piyo")

strs.foreach {
  case ptn(x) => println("number: " + x)
  case _      => println("not found...")
}

こんな感じにすると

not found...
number: 123
number: 456
number: 789

となる。


要は、正規表現中のグループを取り出すことが出来る。


グループが複数の場合はこんな感じ。

val ptn1 = "([0-9]+).*".r
val ptn2 = "([^0-9]+)([0-9]+).*".r
val ptn3 = "[^0-9]*([0-9]+)([^0-9]+)([0-9]+).*".r

val strs = List("hoge", "hoge123", "456piyo", "hoge789piyo", "hoge123piyo456HOGE")

strs.foreach {
  case ptn3(x,y,z) => println("3:[" + x + "," + z +"],[" + y + "]")
  case ptn2(x,y) => println("2:[" + x + "],[" + y + "]")
  case ptn1(x)   => println("1:[" + x + "]")
  case x         => println("not found..." + x)
}

結果は・・・

not found...hoge
2:[hoge],[123]
1:[456]
2:[hoge],[789]
3:[123,456],[piyo]

便利!