[AD] Scalaアプリケーションの開発・保守は合同会社ミルクソフトにお任せください
この記事では、文字列が正規表現に合致するかどうか調べる方法について解説します。
そのうえで、マッチした文字列を取得する方法や、マッチした文字列を別の文字列へと置換する方法も解説します。
末尾には各メソッドの使い分け早見表を掲載しましたので、ぜひご利用ください。
文字列が正規表現に合致しているかどうか調べる
まずは文字列が正規表現に合致するかどうか調べる方法について解説します。
以下の文字列について正規表現を使用してマッチしていきます。
val title = "Scala 2" val titleMajor = "Scala 2.12" val titleMinor = "Scala 2.12.12"
String#matches
メソッドで正規表現に合致しているかどうか調べる
文字列が正規表現に合致しているかどうかを調べるには、
java.lang.String#matches(java.lang.String)
を使用します。
Javapublic boolean matches(String regex)
matches
メソッドの引数には正規表現を表す文字列を渡します。
実行した結果として正規表現に合致すればtrue
、そうでなければfalse
を返します。
それでは、文字列がScalaのバージョンの形式に沿って表記できているかどうかを調べてみましょう。
matches
メソッドを実際に使用すると以下のようになります。
println( title.matches("Scala (\\d{1,2})(.\\d{1,2}){0,2}") ) println( titleMajor.matches("Scala (\\d{1,2})(.\\d{1,2}){0,2}") ) println( titleMinor.matches("Scala (\\d{1,2})(.\\d{1,2}){0,2}") )
3つの文字列について、それぞれ正規表現にマッチしているかどうかを確認しています。
出力は以下のようになります。
true true true
それぞれの実行結果がすべてtrue
を出力しているので、いずれも適切に表記できていることがわかります。
java.lang.String#matches(java.lang.String)
Regex#matches
メソッドで正規表現に合致しているかどうか調べる
Scalaには正規表現を専門に扱うユーティリティクラス scala.util.matching.Regex
が用意されています。
Scala 2.13からは、Regex
クラスにもmatches
メソッドが用意されています。
scala.util.matching.Regex
この用途においては String#matches
メソッドの方が便利ですが、Regex#matches
メソッドについても使い方を確認してみましょう。
def matches(source: CharSequence): Boolean
Regex
クラスは、特定の正規表現を表します。
matches
メソッドに判定したい文字列を投入すると、その正規表現に対して渡した文字列が合致しているかどうかをチェックし、その結果が返ります。
正規表現に合致しているとtrue
、そうでなければfalse
が返ります。
正規表現を表すRegex
クラスのインスタンスは、文字列に対して.r
メソッドを実行することで作成することができます。
正規表現を表す文字列を作成するには、主に「生文字リテラル」「raw
補間子」「文字列リテラル」の3つの方法があります。
サンプルコードはこちらです。
val patternRawLiteral: Regex = """Scala (\d{1,2})(.\d{1,2}){0,2}""".r val patternRawInterpolator: Regex = raw"Scala (\d{1,2})(.\d{1,2}){0,2}".r val patternStringLiteral: Regex = "Scala (\\d{1,2})(.\\d{1,2}){0,2}".r
正規表現を表す文字列は、「生文字リテラル」で作成するのがおすすめです。
正規表現を表現する際における「生文字リテラル」「raw
補間子」の違いに関しては、「raw
補間子」はクォーテーションマーク("
)に対してエスケープする必要があるのに対して、「生文字リテラル」では不要である点が挙げられます。
したがって、Scalapediaとしてはより簡潔に表現できる「生文字リテラル」をお勧めします。
「文字列リテラル」は、バックスラッシュを適切にエスケープする必要があるので、複雑になりがちです。
ごく簡単な正規表現を表現する場合にのみ使用することとし、多少複雑な正規表現を使用する場合には生文字リテラルやraw
補間子を使用しましょう。
それでは、Regex#matches
メソッドを使用してみましょう。
println( patternRawLiteral.matches(title) ) println( patternRawInterpolator.matches(title) ) println( patternStringLiteral.matches(title) )
String#matches
メソッドと比べてみると、正規表現と対象の文字列の順番が入れ替わっているのがわかりますね。
Regex
は、同じ正規表現を複数箇所で使い回す場合にもおすすめできます。
結果は以下のようになります。
true true true
それぞれの実行結果がすべてtrue
を出力しているので、いずれの正規表現もすべて適切に表記できていることがわかります。
scala.util.matching.Regex#matches
正規表現に合致した箇所の文字列を取得する
次に、正規表現に合致するかどうかだけでなく、その合致した箇所の文字列を取得する方法について解説します。
今度はこちらの文字列について正規表現で調べてみましょう。
val text = "本日、Scala 2.12系のマイナーアップデートである Scala 2.12.12 がリリースされました。"
Regex#findFirstIn
メソッドで正規表現に合致した最初の箇所を取得する
Regex#findFirstIn
メソッドを使用すると、正規表現に合致した最初の箇所を取得することができます。
def findFirstIn(source: CharSequence): Option[String]
findFirstIn
メソッドは結果としてOption[String]
を返します。
もし合致していればその内容の文字列をSome
で包んで返します。
そうでなければNoneを返します。
サンプルコードはこちらです。
println( patternRawLiteral.findFirstIn(text) )
出力結果はこちらになります。
Some(Scala 2.12)
1か所目の「2.12」がSome
に包まれて返ってきました。
scala.util.matching.Regex#findFirstIn
Regex#findFirstMatchIn
メソッドで正規表現に合致する最初の箇所を取得する
Regex#findFirstMatchIn
メソッドを使用することによっても、正規表現に合致した最初の箇所を取得することができます。
def findFirstMatchIn(source: CharSequence): Option[Match]
findFirstMatchIn
メソッドは結果としてOption[Match]
を返します。
もし合致していればその内容の文字列をSome
で包んで返します。
そうでなければNoneを返します。
scala.util.matching.Regex.Match
サンプルコードはこちらです。
val result = patternRawLiteral.findFirstMatchIn(text) println(result)
結果は以下のようになります。
Some(Scala 2.12)
正規表現に合致した箇所の文字列をすべて取得する
Regex#findAllIn
メソッドで正規表現に合致した箇所の文字列をすべて取得する
Regex#findAllIn
メソッドを使用すると、正規表現に合致した箇所の文字列をすべて取得することができます。
def findAllIn(source: CharSequence): MatchIterator
findAllIn
メソッドの戻り値はMatchIterator
クラスです。
MatchIterator
クラスは、Match
クラスと同等の機能を持ちつつ、Iterator
として複数のMatch
を扱えるよう実装されているクラスです。
scala.util.matching.Regex.MatchIterator
サンプルコードはこちらです。
patternRawLiteral.findAllIn(text) .foreach(println)
取得して得られたMatch
のそれぞれについて標準出力しています。
実行結果は以下のようになります。
Scala 2.12 Scala 2.12.12
該当する2箇所がすべて取得できていることがわかります。
scala.util.matching.Regex#findAllIn
findAllMatchIn
メソッドで正規表現に合致した箇所の文字列をすべて取得する
Regex#findAllMatchIn
メソッドを使用することによっても、同様に正規表現に合致した箇所の文字列をすべて取得することができます。
def findAllMatchIn(source: CharSequence): Iterator[Match]
findAllMatchIn
メソッドの戻り値はIterator[Match]
です。
MatchIterator
クラスと同等の働きをしつつ、個別のMatch
として分解することもできるようになっています。
サンプルコードはこちらです。
val result = patternRawLiteral.findAllMatchIn(text) result.foreach(println)
取得して得られたMatch
のそれぞれについて標準出力しています。
実行結果は以下のようになります。
Scala 2.12 Scala 2.12.12
こちらも、該当する2箇所がすべて取得できていることがわかります。
scala.util.matching.Regex#findAllMatchIn
文字列の冒頭が正規表現に合致するか調べる
findPrefixOf
メソッドで文字列の冒頭が正規表現に合致するか調べる
def findPrefixOf(source: CharSequence): Option[String]
サンプルコードはこちらです。
println( patternRawLiteral.findPrefixOf(text) )
出力は以下のようになります。
None
対象となる文字列の冒頭にはScalaのバージョン番号は記述されていないので、None
が返ってきています。
scala.util.matching.Regex#findPrefixOf
findPrefixMatchOf
メソッドで文字列の冒頭が正規表現に合致するか調べる
findPrefixMatchOf
メソッドを使用することによっても、文字列の冒頭について正規表現に合致するかどうかを調べることができます。
findPrefixMatchOf
メソッドの戻り値はOption[Match]
ですので、例えば該当箇所の末尾のインデックスを取得したい場合に便利です。
def findPrefixMatchOf(source: CharSequence): Option[Match]
サンプルコードはこちらです。
println( patternRawLiteral.findPrefixMatchOf(text) )
出力結果は以下のようになります。
None
scala.util.matching.Regex#findPrefixMatchOf
正規表現に合致する箇所を置換する
文字列の正規表現に合致する箇所を発見したいのみならず置換したい場合には、こちらの記事をご覧ください。
まとめ(メソッド使い分け早見表)
文字列が正規表現に合致するかどうかを調べたい場合は、以下のメソッドを使用します。
java.lang.String#matches
(おすすめ)scala.util.matching.Regex#matches
文字列中の正規表現に合致する部分文字列を取得・処理したい場合は、Regex
の以下のメソッドを使用します。
メソッド一覧 | 部分文字列だけほしい | 部分文字列以外の他の情報もほしい |
---|---|---|
最初の一つ | findFirstIn | findFirstMatchIn |
合致するもの全部 | findAllIn | findAllMatchIn |
冒頭 | findPrefixOf | findPrefixMatchOf |
マッチした部分文字列の詳しい情報は Match
クラスから取得することができます。
java.lang.String#matches(java.lang.String)
scala.util.matching.Regex#matches
scala.util.matching.Regex.Match