1. 概要

正規表現は、テキスト処理に非常に役立ちます。 このチュートリアルでは、Scalaの scala.util.matching.Regex クラスの機能と、それを実際に使用する方法について学習します。

2. RegexScalaのクラス

scala.util.matching.Regex は、Javajava.util.regexパッケージに基づいています。 非常にクリーンで簡潔なAPIを提供します。 さらに、パターンマッチングを使用すると、Regexクラスの読みやすさが向上します。

Regexオブジェクトを定義する方法は2つあります。 まず、明示的に作成します。

val polishPostalCode = new Regex("([0-9]{2})\\-([0-9]{3})")

次に、 r メソッドを使用します。これは、同じことを行うための標準的なScalaのような方法です。

val polishPostalCode = "([0-9]{2})\\-([0-9]{3})".r

それでは、Regexを使用した正規表現の一般的な使用例を詳しく見ていきましょう。

3. 一致するものを見つける

最も一般的な使用例の1つは、テキストで一致するものを見つけることです。

findFirstIn メソッドを使用できます。このメソッドは、 Option[String]オブジェクトを返します。

val postCode = polishPostalCode.findFirstIn("Warsaw 01-011, Jerusalem Avenue")
assertEquals("01-011", postCode)

または、 findFirstMatchIn を使用して、 Option[Match]を返すこともできます。

val postCodes = polishPostalCode.findFirstMatchIn("Warsaw 01-011, Jerusalem Avenue")
assertEquals(Some("011"), for (m <- postCodes) yield m.group(2))

すべての一致を検索するために、同様の名前のメソッドがあります。MatchIteratorを返すfindAllIn

val postCodes = polishPostalCode.findAllIn("Warsaw 01-011, Jerusalem Avenue, Cracow 30-059, Mickiewicza Avenue")
  .toList
assertEquals(List("01-011", "30-059"), postCodes)

およびIterator[Match]を返すfindAllMatchIn

val postCodes = polishPostalCode.findAllMatchIn("Warsaw 01-011, Jerusalem Avenue, Cracow 30-059, Mickiewicza Avenue")
  .toList
val postalDistricts = for (m <- postCodes) yield m.group(1)
assertEquals(List("01", "30"), postalDistricts)

4. 値の抽出

正規表現が一致すると、パターンマッチングを使用したエクストラクタとしてRegexを使用できます。

val timestamp = "([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{3})".r
val description = "11:34:01.411" match {
  case timestamp(hour, minutes, _, _) => s"It's $minutes minutes after $hour"
}

assertEquals("It's 34 minutes after 11", description)

デフォルトでは、正規表現は、パターンが「固定」されているかのように動作します。つまり、文字の中央に配置されます ^ $ –「^ pattern $」。ただし、これらは削除できます。 UnanchoredRegex クラスのアンカーなしメソッドを使用した文字:

val timestampUnanchored = timestamp.unanchored

これで、試合の前後に追加のテキストを配置できますが、それでも見つけることができます。

val description = "Timestamp: 11:34:01.411 error appeared" match {
  case timestampUnanchored(hour, minutes, _, _) => s"It's $minutes minutes after $hour"
}

assertEquals("It's 34 minutes after 11", description)

5. テキストの置き換え

もう1つの重要な機能は、テキストの置き換えです。 オーバーロードされたreplaceAllInメソッドでそれを達成できます。

val minutes = timestamp.replaceAllIn("11:34:01.311", m => m.group(2))

assertEquals("34", minutes)

また、この関数をパターンマッチングとうまく組み合わせることができます。

val secondsThatDayInTotal = timestamp.replaceAllIn("11:34:01.311", _ match {
  case timestamp(hours, minutes, seconds, _) => s"$hours-$minutes"
})

assertEquals("11-34", secondsThatDayInTotal)

6. 結論

このチュートリアルでは、Scalaの標準ライブラリにあるRegexクラスを紹介しました。 これまで見てきたように、これは最も一般的な正規表現のユースケースに役立つ非常に読みやすいAPIを提供します。

いつものように、完全なソースコードはGitHubにあります。