Scala 正規表現のパターンマッチ match case式による直接処理

Scala パターンマッチ

Scalaでは文字列をマッチングさせる場合、match式で処理を書くことができます。

"abcdef" match {
  case "abcdef" => println("match")
  case _ => println("not match")
 }

上記のような直接比較では問題ないのですが、正規表現を使う場合に悩んだので、はまった個所をまとめました。

正規表現を直接書いてもマッチしない

case文に正規表現を記載しても正規表現として認識してくれません。

"abcdef" match {
  case "^(ab).*" => println("match")  // マッチしない
  case _ => println("not match")
}

scala.util.matching.Regex正規表現を使う

正規表現パターンは文字列に"r"メソッドを適用すれば取得できます。

val matchPattern: Regex = "ab.*".r
"abcdef" match {
  case "^ab.*".r => println("match line1")  // 直接書くとコンパイルできない
  case matchPattern() => println("match line2")  // マッチする
  case _ => println("not match")
}

マッチした個所の取得

マッチした個所を取得したい場合、()で囲みグループを使用することにより取得できます。 ただしマッチしたグループすべてが返るため、引数の数とグループ数が合わないとマッチしません。

val matchPattern: Regex = "^(ab).*(ef)$".r
"abcdef" match {
  case matchPattern() => println("match line1")  // マッチしない
  case matchPattern(s1) => println(s"match line2: $s1")  // マッチしない
  case matchPattern(s1, s2) => println(s"match line3 : $s1, $s2")  // マッチする
  case _ => println("not match")
}

改行を含んだ文字列との比較

Scalaに限ったことではないですが、文字列に改行が含まれている場合マッチしなくなります。 これは "." が「Match any character except newline(改行を除いた文字)」となっているためです。 "." を "[\\s|\\S]"に変更することによりマッチ可能となります。

expression match
\\s Matches whitespace. Equivalent to [\t\n\r\f].
\\S Matches nonwhitespace.
val matchPattern: Regex = "^(ab).*(ef)[\\s|\\S]*".r
"abcdefgh\r\n" match {
  case matchPattern(s1, s2) => println(s"match: $s1, $s2")
  case _ => println("not match")
}