Rubyでプログラミングする際に必ずといっていいほど出くわす、文字列を取り扱った処理。大量のテキストデータを取り扱うことが想定されるような開発案件の場合は、文字列の検索処理や置換処理の実装スキルがなければ、開発は困難を極めます。
今回は、文字列処理の中でも基本的な文字列の置換処理、特にRubyで用意されている文字列置換処理の機能を持つ、gsub()メソッドの使用方法について詳しく解説します。
似た機能を持つメソッドとの動作の違いについても併せて解説しましたので、プログラミングスキル向上にお役立てください。
なお、Rubyの魅力や特徴については以下の記事で詳しく解説していますので、こちらもぜひご覧くださいね。
みなさんこんにちは! 今回の記事は、 悩みを抱えた人 ・Rubyってどんなプログラミング言語なの?・Rubyを勉強すると将来役に立つかな?・Rubyのおすすめの学習方法が知りたい! というお悩みを解決する記事にな[…]
フリーランス案件を探すならこのエージェント!
転職を考えているならこのエージェント!
gsub()メソッドとは?
gsub()メソッドは、RubyのStringクラスにて実装されているインスタンスメソッドの1つです。もともと存在する文字列を検査して、一部分の文字列を別の文字列に置き換えたものを新たな文字列として作成する機能を持ちます。
gsub()メソッドの簡単な使用例を、以下のサンプルコードに示しました。
# 「mno」が間違いであるため「xyz」に置き換えたい
sample_text = 'The alphabet begins with "abc" and ends with "mno"'
# gsub()メソッドで文字列を置き換えよう
fixed_text = sample_text.gsub("mno", "xyz")
p fixed_text # "The alphabet begins with \"abc\" and ends with \"xyz\""
サンプルコードでは、英文中に不適切な箇所が含まれるため、該当箇所を適切な文字列に置き換える処理を実装しています。
置換処理の中核とも言える部分は、5行目におけるgsub()メソッドです。不適切な箇所、つまり置換前の文字列である「mno」と、置換後の文字列「xyz」を引数として設定することで、文字列sample_text中の「mno」の部分が「xyz」に置き換わった文字列が返されます。
戻り値を格納した文字列fixed_textをコンソール出力すると、文字列が置換されていることが分かります。
置換対象の文字列を検索する方法
gsub()メソッドの第一引数にあたる置換前の文字列は、以下の2通りの指定方法が存在します。
- 文字列リテラルで指定する方法
- 正規表現で指定する方法
文字列リテラルで指定する方法
1つ目は、文字列リテラルで指定する方法です。
文字列リテラルとは、プログラミング上の概念の一つで、文字列をシングルクオート、またはダブルクオートで囲んだものを指します。「gsub()メソッドとは?」で示したサンプルコードも、「mno」をダブルクオートで囲んだものを引数として渡しています。これが文字列リテラルです。
文字列リテラルで指定する際に注意すべきは、文字列リテラルを表現するのに必要な記号である、シングルクオートとダブルクオートが置換対象である場合です。
このような場合は、バックスラッシュを付与してエスケープ処理を施しましょう。以下のサンプルコードを実行して、バックスラッシュによるエスケープ処理で、置換処理が正常に動作していることを確認しましょう。
sample_text_1 = '\'シャープで囲まれています\''
# シングルクオートで表現する場合
# シングルクオートをバックスラッシュでエスケープ
fixed_text = sample_text_1.gsub('\'', "#")
p fixed_text # "#シャープで囲まれています#"
sample_text_2 = "\"黒丸で囲まれています\""
# ダブルクオートで表現する場合
# ダブルクオートをバックスラッシュでエスケープ
fixed_text = sample_text_2.gsub("\"", "●")
p fixed_text # "●黒丸で囲まれています●"
正規表現で指定する方法
gsub()メソッドは、文字列リテラル以外にも正規表現で指定する方法にも対応しています。
正規表現は、文字列リテラルとは異なる文字列の表現方法で、文字列を検索することに特化しています。正規表現を用いた文字列の置換処理のサンプルプログラムを以下に示します。
sample_text = "This brogrdm is a sample."
# 正規表現では、置換対象文字列をスラッシュで挟み込むことで表現
fixed_text = sample_text.gsub(/brogrdm/, "program")
p fixed_text # "This program is a sample."
# アルファベットの小文字全てを「#」に置換
# [a-z]は、aからzの任意の一文字を示す
hidden_text = sample_text.gsub(/[a-z]/, "#")
p hidden_text # "T### ####### ## # ######."
正規表現で指定するには、サンプルコード4行目にあるように置換対象の文字列をスラッシュで挟むように表記します。これが正規表現の基本形です。
今回は、文字列sample_textの「brogrdm」が不適切なため、引数は「/brogrdm/」を設定します。5行目のコンソール出力では、正常に置換された文字列が出力されることが分かります。
正規表現では、さまざまな記号と組み合わせて記述することで、複雑な条件の文字列検索を実現できるのが大きなメリットです。
例えば、サンプルコードの9行目にある「/[a-z]/」は、aからzの範囲内にある任意の1文字を意味しています。つまり、アルファベットの小文字すべてを置換対象とみなすのです。10行目のコンソール出力を見ると、頭文字のTと半角スペース以外が、すべて「#」に置換された文字列が設定されていることが分かります。
gsub()メソッドの応用的な使い方
ここでは、gsub()メソッドの応用的な使い方について解説していきます。
元の文字列に別の文字列を追加する
「div」に記号を付加して「<div>」に置き換えたいケースの場合は、gsub()メソッドを使って以下のように実装することで置換処理を実現できます。
html_text = 'The div is one of the html tags.'
# \&には置換前の文字列が挿入される
fixed_text = html_text.gsub(/div/, '<\&>')
p fixed_text # "The <div> is one of the html tags."
サンプルコード4行目のgsub()メソッドの第二引数で表記されている「\&」は、置換前の文字列を示す特殊な記号です。今回は、「div」を置き換えたいため「\&」には「div」が設定されていると考えるようにしましょう。「\&」の前後に文字列を記すことによって、置換前の文字列に別の文字列を追加する形で、置換処理を実行できます。
条件に応じて置き換える文字列を変化させる
続いては、金額が列挙された文字列を、2割引した金額に置き換えたいケースを考えてみましょう。2割引した金額は元の金額によって異なるため、置換後の金額を求めるための計算処理が必要です。
gsub()メソッドは、ブロックによる実装に対応しています。したがって、以下のサンプルコードのように実装することで、置換処理を実行できます。
menu_text = "かけそば:350円、かき揚げそば:430円、えび天そば:470円、カツ丼セット:620円"
discount_text = menu_text.gsub(/(\d+)円/) { |price|
# 文字列から数値に変換
price_int = price.to_i
# 2割引後の価格を計算
dis_price = price_int * 0.8
# 小数点以下を切り捨て
dis_price = dis_price.floor
# 数値から文字列に変換し、「円」と連結
fixed_price = dis_price.to_s + "円"
}
p discount_text # "かけそば:280円、かき揚げそば:344円、えび天そば:376円、カツ丼セット:496円"
ブロックの引数であるpriceには、置換前の文字列が格納され、置換する個数分ブロック内に定義された処理が実行されます。そして、最後に評価された値(fixed_price)が置換後の文字列として、置換処理されます。
複数パターンの置換処理を一括実行する
gsub()メソッドは、第二引数にハッシュを渡すことによって、複数のパターンの置換処理を、一度のメソッド呼び出しで一括処理できます。サンプルコードは以下の通りです。
introduction_text = "Rails on Ruby is a web application framework."
# 置換する文字列ごとにハッシュに定義
replace_pattern = {"Rails" => "Ruby", "Ruby" => "Rails"}
# ハッシュを引数に渡して一括置換
fixed_text = introduction_text.gsub(/Ruby|Rails/, replace_pattern)
p fixed_text # "Ruby on Rails is a web application framework."
gsub()メソッドの第二引数に渡すハッシュは、「置換前の文字列 => 置換後の文字列」の形で要素を定義しましょう(4行目)。
また、第一引数は正規表現で「/1つ目の文字列|2つ目の文字列/」のように、置換対象の文字列をパイプで区切るように表現します。これにより、一回gsub()メソッドを呼び出すだけで、文字列の置換処理が数パターン一括で実行できます。
似た機能を持つメソッド
ここでは、gsub()メソッドと似たような機能をもつメソッドを2つ紹介します。
gsub!()メソッド
1つ目は、gsub!()メソッドです。
元の名前にビックリマークが付与されたgsub!()メソッドは、破壊的メソッドと呼ばれる種類のメソッドに分類されます。対して、gsub()メソッドは非破壊的メソッドに分類されます。それぞれどのような点が異なるのか、以下のサンプルコードで確認しましょう。
self_introduction_text_1 = "私の名前は田中花子です"
self_introduction_text_2 = "私の名前は田中花子です"
self_introduction_text_1.gsub("田中花子", "鈴木花子")
self_introduction_text_2.gsub!("田中花子", "鈴木花子")
# gsub()メソッドはレシーバが変化しない
p self_introduction_text_1 # "私の名前は田中花子です"
# gsub!()メソッドはレシーバが更新される
p self_introduction_text_2 # "私の名前は鈴木花子です"
同一の文章を別々の変数で用意し、gsub()メソッド・gsub!()メソッドそれぞれで文字列置換を実施する処理を実装しています。両者の違いを把握するポイントは、レシーバの状態変化です。
gsub()メソッドで文字列置換を実施した場合、レシーバは更新されない一方で、gsub!()メソッドで実施した場合は、レシーバが置換後の文字列に更新されます。
このように、非破壊的メソッドで処理を実行した場合、実行結果は戻り値として返され、破壊的メソッドで実行した場合は、実行結果が戻り値で返されるのに加えて、レシーバが上書きされるという特性を持ちます。
文字列置換処理の実装に際して、新しく変数を用意するのが煩わしい場面では、破壊的メソッドを使って実装すのが適切といえます。
sub()メソッド
2つ目は、sub()メソッドです。非常に似た名前のメソッドで、gsub()メソッドと同じく文字列を置換する機能を持ちます。では一体、どのような部分でgsub()メソッドと機能を異にするのか、以下のサンプルコードで確認しましょう。
continuous_call_text = "PHP! PHP! PHP!"
fixed_text_1 = continuous_call_text.gsub("PHP", "Ruby")
fixed_text_2 = continuous_call_text.sub("PHP", "Ruby")
# gsub()メソッドは、対象の文字列すべてを置き換え
p fixed_text_1 # "Ruby! Ruby! Ruby!"
# sub()メソッドは、対象の文字列のうち先頭部分のみ置き換え
p fixed_text_2 # "Ruby! PHP! PHP!"
違いを見極めるポイントは、置換処理を行う文字列の個数です。gsub()メソッドが、該当する文字列すべてを置き換えるのに対し、sub()メソッドは、複数該当する中で最初に発見された要素のみを置換するという特性を持ちます。
最後に
さて、ここまでRubyのgsub()メソッドの使い方について解説してきましたがいかがでしたか?
「文字列の置換」と聞くと少し難しそうな印象を持つ方も多いかもしれませんが、今回ご紹介した通り、gsub()メソッドを使用すれば比較的簡単に実装することが可能です。
最後にご紹介したgsub!()メソッドやsub()メソッドとの違いを考えながら、実際の開発でも積極的に使っていってくださいね。
このブログを通じて少しでも「傍(はた)を楽(らく)にする」ことができていれば嬉しく思います。
最後まで読んで頂きありがとうございました。