文字列が正規表現に合致するか調べる方法

Scala 3 (Dotty 0.26.0-RC1) 2.13.3 2.12.12
最終更新:2020年7月15日

[AD] scalapediaでは記事作成ボランティアを募集しています

この記事では、文字列が正規表現に合致するかどうか調べる方法について解説します。

そのうえで、マッチした文字列を取得する方法や、マッチした文字列を別の文字列へと置換する方法も解説します。

末尾には各メソッドの使い分け早見表を掲載しましたので、ぜひご利用ください。

文字列が正規表現に合致しているかどうか調べる

まずは文字列が正規表現に合致するかどうか調べる方法について解説します。

以下の文字列について正規表現を使用してマッチしていきます。

val title = "Scala 2" val titleMajor = "Scala 2.12" val titleMinor = "Scala 2.12.12"

String#matchesメソッドで正規表現に合致しているかどうか調べる

文字列が正規表現に合致しているかどうかを調べるには、 java.lang.String#matches(java.lang.String) を使用します。

Java
public 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を出力しているので、いずれも適切に表記できていることがわかります。

Regex#matchesメソッドで正規表現に合致しているかどうか調べる

Scalaには正規表現を専門に扱うユーティリティクラス scala.util.matching.Regexが用意されています。

Scala 2.13からは、Regexクラスにもmatchesメソッドが用意されています。

Scala Standard Library: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 Standard Library: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 Standard Library:scala.util.matching.Regex#findFirstIn

Regex#findFirstMatchInメソッドで正規表現に合致する最初の箇所を取得する

Regex#findFirstMatchInメソッドを使用することによっても、正規表現に合致した最初の箇所を取得することができます。

def findFirstMatchIn(source: CharSequence): Option[Match]

findFirstMatchInメソッドは結果としてOption[Match]を返します。
もし合致していればその内容の文字列をSomeで包んで返します。
そうでなければNoneを返します。

Matchクラスは合致した文字列そのものだけでなく、合致した部分文字列の位置を示すインデックスや、正規表現の()で囲んだサブグループに関する情報も保持するクラスです。

Scala Standard Library:scala.util.matching.Regex.Match

サンプルコードはこちらです。

val result = patternRawLiteral.findFirstMatchIn(text) println(result) result.foreach(data => println(data.groupNames) )

文字列の内容だけでなく、サブグループ名についても取得して出力しています。

結果は以下のようになります。

Some(Scala 2.12) List()

文字列の内容は期待通り出力されています。

取得したサブグループ名については、空のリストが出力されています。
サブグループは存在していないので、これは期待通りの挙動です。

正規表現に合致した箇所の文字列をすべて取得する

Regex#findAllInメソッドで正規表現に合致した箇所の文字列をすべて取得する

Regex#findAllInメソッドを使用すると、正規表現に合致した箇所の文字列をすべて取得することができます。

def findAllIn(source: CharSequence): MatchIterator

findAllInメソッドの戻り値はMatchIteratorクラスです。

MatchIteratorクラスは、Matchクラスと同等の機能を持ちつつ、Iteratorとして複数のMatchを扱えるよう実装されているクラスです。

サンプルコードはこちらです。

patternRawLiteral.findAllIn(text) .foreach(println)

取得して得られたMatchのそれぞれについて標準出力しています。

実行結果は以下のようになります。

Scala 2.12 Scala 2.12.12

該当する2箇所がすべて取得できていることがわかります。

Scala Standard Library: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箇所がすべて取得できていることがわかります。

文字列の冒頭が正規表現に合致するか調べる

findPrefixOfメソッドで文字列の冒頭が正規表現に合致するか調べる

def findPrefixOf(source: CharSequence): Option[String]

サンプルコードはこちらです。

println( patternRawLiteral.findPrefixOf(text) )

出力は以下のようになります。

None

対象となる文字列の冒頭にはScalaのバージョン番号は記述されていないので、Noneが返ってきています。

findPrefixMatchOfメソッドで文字列の冒頭が正規表現に合致するか調べる

findPrefixMatchOfメソッドを使用することによっても、文字列の冒頭について正規表現に合致するかどうかを調べることができます。

findPrefixMatchOfメソッドの戻り値はOption[Match]ですので、例えば該当箇所の末尾のインデックスを取得したい場合に便利です。

def findPrefixMatchOf(source: CharSequence): Option[Match]

サンプルコードはこちらです。

println( patternRawLiteral.findPrefixMatchOf(text) )

出力結果は以下のようになります。

None

正規表現に合致する箇所を置換する

文字列の正規表現に合致する箇所を発見したいのみならず置換したい場合には、こちらの記事をご覧ください。

まとめ(メソッド使い分け早見表)

文字列が正規表現に合致するかどうかを調べたい場合は、以下のメソッドを使用します。

  • java.lang.String#matches(おすすめ)
  • scala.util.matching.Regex#matches

文字列中の正規表現に合致する部分文字列を取得・処理したい場合は、Regexの以下のメソッドを使用します。

メソッド一覧部分文字列だけほしい部分文字列以外の他の情報もほしい
最初の一つfindFirstInfindFirstMatchIn
合致するもの全部findAllInfindAllMatchIn
冒頭findPrefixOffindPrefixMatchOf

マッチした部分文字列の詳しい情報は Match クラスから取得することができます。

Scala Standard Library:scala.util.matching.Regex#matches
Scala Standard Library:scala.util.matching.Regex.Match

サイト内検索


カテゴリ「文字列処理」の記事

文字列をエスケープしたり復元したりする方法(Apache Commons Text) JavaとScalaのString/StringBuilder/StringBuffer使い分け事情 文字列を分割する方法(split・splitAt・linesIterator・linesWithSeparatorsメソッド) trimメソッドで文字列の前後の空白を除去する 文字列が一致するか比較する方法/大文字・小文字を区別せずに比較する方法 特定の文字の文字コード(コード・ポイント)を取得する replaceメソッドなど、文字列を置換する方法を紹介 文字列の先頭や末尾を、取得したり切り落としたりする方法 containsメソッドでStringに特定の文字列が含まれるか調べる方法 数値を文字列に変換する方法 stripメソッドで文字列の前後の全角空白を除去する 文字列を数値に変換するには?to○○メソッドと注意点について 文字列を辞書的に比較する方法/大文字・小文字を区別せずに比較する方法 文字列が特定の文字列で始まるか・終わるかを調べる方法 【getBytes&size】文字列のバイト長を取得する方法 substringでStringを切り取り、部分文字列を抽出する方法 StringOpsとWrappedStringの違いは? 文字列を連結するには?+演算子やString interpolationの使い方 文字列の大文字へ・小文字へ変換する方法 文字列を逆順にする方法 文字列の文字コード(文字セット)を変換する方法 文字列の長さを取得する方法:lengthとcodePointCountの使い分け 文字列をURLエンコード・デコードする方法 文字列が正規表現に合致するか調べる方法 この文字の位置はどこ?文字列のインデックスを取得する方法 文字列をバイト列に、またはバイト列を文字列に変換する方法

カテゴリ「文字列処理」の記事

文字列をエスケープしたり復元したりする方法(Apache Commons Text) JavaとScalaのString/StringBuilder/StringBuffer使い分け事情 文字列を分割する方法(split・splitAt・linesIterator・linesWithSeparatorsメソッド) trimメソッドで文字列の前後の空白を除去する 文字列が一致するか比較する方法/大文字・小文字を区別せずに比較する方法 特定の文字の文字コード(コード・ポイント)を取得する replaceメソッドなど、文字列を置換する方法を紹介 文字列の先頭や末尾を、取得したり切り落としたりする方法 containsメソッドでStringに特定の文字列が含まれるか調べる方法 数値を文字列に変換する方法 stripメソッドで文字列の前後の全角空白を除去する 文字列を数値に変換するには?to○○メソッドと注意点について 文字列を辞書的に比較する方法/大文字・小文字を区別せずに比較する方法 文字列が特定の文字列で始まるか・終わるかを調べる方法 【getBytes&size】文字列のバイト長を取得する方法 substringでStringを切り取り、部分文字列を抽出する方法 StringOpsとWrappedStringの違いは? 文字列を連結するには?+演算子やString interpolationの使い方 文字列の大文字へ・小文字へ変換する方法 文字列を逆順にする方法 文字列の文字コード(文字セット)を変換する方法 文字列の長さを取得する方法:lengthとcodePointCountの使い分け 文字列をURLエンコード・デコードする方法 文字列が正規表現に合致するか調べる方法 この文字の位置はどこ?文字列のインデックスを取得する方法 文字列をバイト列に、またはバイト列を文字列に変換する方法