[AD] Scalaアプリケーションの開発・保守は合同会社ミルクソフトにお任せください
Scalaの文字列で置換を行う方法をご紹介します。
文字列で指定する
マッチした部分すべてを置換する
最も単純な置換は、以下のようにStringクラスのreplaceメソッドを用いて、置換対象と置換先の文字列を指定することで行います。
val str = "hello abc" println(str.replace("abc", "world"))
結果は以下のように出力されます。
hello world
replaceメソッドはマッチした文字列すべてを置換します。
val str = "foofoofoobar" println(str.replace("foo", "bar"))
以下のようにすべて置換されて出力されます。
barbarbarbar
最初にマッチした部分のみを置換する
最初にマッチした部分のみを置換したい場合、replaceFirstメソッドを使うことで解決することができます。
val str = "foofoofoobar" println(str.replaceFirst("foo", "bar"))
以下のように先頭のみ置換されて出力されます。
barfoofoobar
先頭一文字のみ置換する
文字列の先頭一文字を置き換えたい場合、tailメソッドを使うと解決できます。
tailメソッドは文字列の先頭から一文字取り除いたものを返します。
val str = "fello world" println("h" + str.tail)
以下のように出力されます。
hello world
末尾一文字のみ置換する
また、末尾一文字を置き換えたい場合は、initメソッドを使うことで解決できます。
initメソッドはtailメソッドとは反対に末尾一文字を取り除いたものを返します。
val str = "hello worlo" println(str.init + "d")
以下のように出力されます。
hello world
位置を指定して一文字のみ置換する
位置を指定して一文字だけを置換したい場合は、updatedメソッドを使うと解決できます。
println("helio world".updated(3, 'l'))
以下のように出力されます。
hello world
正規表現を使う
文字列を正規表現として扱う
正規表現によるマッチで置換を行いたい場合、replaceAllメソッドを使うことで解決することができます。
例えば、以下のようにアルファベットの部分を置き換えたい場合。
val str = "00000agkkjpaviwadsd00000" println(str.replaceAll("[A-z]+", "foo"))
以下のように出力されます。
00000foo00000
replaceAllメソッドはreplaceメソッドと違い、第一引数を正規表現と解釈して置換を行います。
Regexオブジェクトによる置換
これまではJavaのStringのメソッドによる置換を紹介してきました。
ここからはScalaのRegexクラスを使った置換を紹介していきます。
Regexクラスでは置換を始め、正規表現を使ったメソッドを多く提供しています。
Stringクラスのrメソッドを使うことでRegexオブジェクトを作ることができます。
マッチした最初の部分を置換する
replaceFirstInメソッドではマッチした最初の部分を置換してくれます。
val re = "[A-z]+".r // Regexオブジェクトに変換 println(re.replaceFirstIn("aaaa111bbb1222ccc", "000"))
以下のように出力されます。
000111bbb1222ccc
マッチしたすべての部分を置換する
マッチしたすべての部分を置換するにはreplaceAllInメソッドを使います。
val re = "[A-z]+".r println(re.replaceAllIn("aaaa111bbb1222ccc", "000"))
以下のように出力されます。
0001110001222000
マッチした部分すべてに関数を適用して置換する
replaceAllInメソッドは第二引数にMatchオブジェクトを引数にとる関数を受け取ります。
以下はマッチした文字列を1文字だけ切り取り置換する例です。
val re = "[A-z]+".r println(re.replaceAllIn("aaaa111bbb1222ccc", m => m.group(0).substring(0, 1)))
mはMatchオブジェクトで、group(0)でマッチした部分をStringで取得しています。
最後にsubstringメソッドで0文字目から1文字を切り出して置換させています。
以下のように出力されます。
a111b1222c
コレクションを使って置換する
ListやSeqといったコレクションで置換したい文字列を複数指定したい場合、mkStringメソッドを使うことで解決できます。
引数を1つ取るmkStringメソッドは、セパレータとなる文字列を指定してあげることで、その文字を使ってリストの要素を連結してくれます。
println(List("foo", "bar").mkString("|").r.replaceAllIn("foobarbaz", "X"))
|で連結することでListのすべての要素にマッチするよう正規表現を組み立てています。
以下のように出力されます。
XXbaz
Seqの場合も同様に行えます。
println(Seq("foo", "bar").mkString("|").r.replaceAllIn("foobarbaz", "X"))
結果も同じく以下の通りです。
XXbaz
特殊文字を置換する
エスケープを使うことで、特殊文字も置換させることができます。
例えば、以下は.を置換する例です。
.は通常任意の一文字を意味しますが、\\.とすることで、ただの.として解釈させることができます。
val re = "\\.".r println(re.replaceAllIn(raw"hello.world", " "))
以下のように出力されます。
hello world
"の場合、"\""とすることでエスケープが可能です。
以下は"Hello World"な文字列から"を取り除く例です。
Scalaでは"を3つにすることで特殊文字をエスケープすることができます。
val re = "\"".r println(re.replaceAllIn(""""hello world"""", ""))
以下のように出力されます。
hello world
StringBuilderを使う
不変なStringクラスは置換を行うたびに新しいオブジェクトを生成するため、メモリの消費が大きくなります。
そこで、可変なStringBuilderクラスのreplaceメソッドの紹介をします。
第一引数に置換開始地点、第二引数に終了地点を指定し、第三に置換後の文字列を指定します。
そのため、予め置換を行う範囲を知っておく必要があります。
範囲を指定し、abcをworldに置換する例です。
val sb = new StringBuilder("hello abc") println(sb.replace(6, 9, "world").toString())
以下のように出力されます。
hello world