今まであまり触れてこなかったので、メモを兼ねて試してみることにしました。
普通にメソッド呼び出し
val targetString = "Hello 1234 World 5678" val numberPattern = """\d+""".r val alphaPattern = """[a-zA-Z]+""".r // Regex#findFirstIn => Option[String] numberPattern.findFirstIn(targetString) // => Some(1234) alphaPattern.findFirstIn(targetString) // => Some(Hello) // Regex#findFirstMatchIn => Option[Match] numberPattern.findFirstMatchIn(targetString) // => Some(1234) alphaPattern.findFirstMatchIn(targetString) // => Some(Hello) // Regex#findAllIn => MatchIterator numberPattern.findAllIn(targetString).mkString("[", ", ", "]") // => [1234, 5678] alphaPattern.findAllIn(targetString).mkString("[", ", ", "]") // => [Hello, World] // Regex#findPrefixOf => Option[String] numberPattern.findPrefixOf(targetString) // => None alphaPattern.findPrefixOf(targetString) // => Some(Hello) // Regex#findPrefixMatchOf => Option[Match] numberPattern.findPrefixMatchOf(targetString) // => None alphaPattern.findPrefixMatchOf(targetString) // => Some(Hello) // Regex#split => Array[String] numberPattern.split(targetString).mkString("[", ", ", "]") // => [Hello , World ] alphaPattern.split(targetString).mkString("[", ", ", "]") // => [, 1234 , 5678] """,""".r.split(targetString).mkString("[", ", ", "]") // => [Hello 1234 World 5678] // Regex#replaceFirstIn => String numberPattern.replaceFirstIn(targetString, "number") // => Hello number World 5678 alphaPattern.replaceFirstIn(targetString, "alpha") // => alpha 1234 World 5678 // Regex#replaceAllIn(String, String) => String numberPattern.replaceAllIn(targetString, "number") // => Hello number World number alphaPattern.replaceAllIn(targetString, "alpha") // => alpha 1234 alpha 5678 // Regex#replaceAllIn(String, (Match => String)) => String numberPattern.replaceAllIn(targetString, m => "number") // => Hello number World number alphaPattern.replaceAllIn(targetString, m => m.group(0)) // => Hello 1234 World 5678 // Regex#replaceSomeIn(String, (Match => Option[String])) => String numberPattern.replaceSomeIn(targetString, m => Some("number")) // => Hello number World number alphaPattern.replaceSomeIn(targetString, m => None) // => Hello 1234 World 5678
この使い方だと、パターン構築時にグループ化を使っても
val numberPattern = """(\d+)""".r val alphaPattern = """([a-zA-Z]+)""".r
使わなくても
val numberPattern = """\d+""".r val alphaPattern = """[a-zA-Z]+""".r
結果は変わりません。
名前付きグループ化
これは、素直にAPIリファレンスの例がわかりやすいかも。
import scala.util.matching.Regex val datePattern = new Regex("""(\d\d\d\d)-(\d\d)-(\d\d)""", "year", "month", "day") val text = "From 2011-07-15 to 2011-07-17" val repl = datePattern replaceAllIn (text, m => m.group("month")+"/"+m.group("day")) // => From 07/15 to 07/17
まあ、Matchオブジェクトが返却されたり、コールバック関数にMatchオブジェクトを取るものに使うんでしょうね。
import scala.util.matching.Regex val targetString = "Hello 1234 World 5678" val numberPattern = new Regex("""(\d+)(?:[^\d]+)(\d+)""", "firstNumber", "secondNumber") val alphaPattern = new Regex("""([a-zA-Z]+)(?:[^a-zA-Z]+)([a-zA-Z])""", "firstAlpha", "secondAlpha") // Regex#findFirstMatchIn => Option[Match] numberPattern.findFirstMatchIn(targetString).foreach(m => println(m.group("secondNumber"))) // => 5678 alphaPattern.findFirstMatchIn(targetString).foreach(m => println(m.group("firstAlpha"))) // => Hello // Regex#findPrefixMatchOf => Option[Match] numberPattern.findPrefixMatchOf(targetString).foreach(m => println(m.group("secondNumber"))) // => 出力なし alphaPattern.findPrefixMatchOf(targetString).foreach(m => println(m.group("firstAlpha"))) // => Hello // Regex#replaceAllIn(String, (Match => String)) => String numberPattern.replaceAllIn(targetString, m => m.group("firstNumber") + ":" + m.group("secondNumber")) // => Hello 1234:5678 alphaPattern.replaceAllIn(targetString, m => m.group("firstAlpha") + ":" + m.group("secondAlpha")) // => Hello:World 5678 // Regex#replaceSomeIn(String, (Match => Option[String])) => String numberPattern.replaceSomeIn(targetString, m => Some(m.group("firstNumber"))) // => Hello 1234 alphaPattern.replaceSomeIn(targetString, m => None) // => Hello 1234 World 5678
なんか、名前付きグループ化をreplaceAllInとかreplaceSomeInとかの中で使うと、置換はその1回で終わってしまうっぽい?APIリファレンスの例から考えると、名前を付けたパターン自体が繰り返しマッチしないと、複数回の呼び出しにはならないんでしょうね。
パターンマッチング
けっこう有名な割には、地味に癖があるような??
val targetString = "Hello 1234 World 5678" val regex = """ ([a-zA-Z]+) """.r regex.findAllIn(targetString).foreach(println) // => World targetString match { case regex(world) => println("Matched[%s]".format(world)) case _ => println("Not Match") } // => Not Match
こんな感じで、文字列中の一部だけを書いたパターンだとキャプチャに失敗します。
パターンマッチングでキャプチャできるようにするには、文字列全体にマッチするパターンで書かないとダメっぽいですね。
val targetString = "Hello 1234 World 5678" val regex = """([a-zA-Z]+) \d+ ([a-zA-Z]+) \d+""".r regex.findAllIn(targetString).foreach(println) // => Hello 1234 World 5678 targetString match { case regex(hello, world) => println("Matched[%s, %s]".format(hello, world)) case _ => println("Not Match") } // => Matched[Hello, World]