こんにちは!Webコーダー・プログラマーの貝原(@touhicomu)です。
今日は、Rubyの文字列の検索について、書きたいと思います。
Rubyをプログラミングしていると、「文字列の中の文字を検索したい!」と思う場面によく出会いますよね。
特にRubyは文字列処理が得意分野の一つですし、文字列の検索は押さえておきたいテクニックです。
そうなると、「どんな文字列検索のメソッドがあるのか知りたい!」と思うものです。
さらに、Rubyの文字列の扱いに慣れるつれ、「文字列検索のメソッドの使い分けを知りたい!」と思うようになるのもうなづけます。
そこで!今回は、Rubyの文字列の検索メソッドのすべてについてまとめてみました。
indexメソッドによる文字列の検索
indexメソッドは、文字列の中に指定の文字列が含まれているか確かめるメソッドです。
indexメソッドは、検索文字がレシーバの文字列の中で何文字目の位置に出てくるか検索し、その何文字目かを返します。文字が見つからなければnilを返します。
なお、indexメソッドは、レシーバの文字列の左端の文字から右側に向かって検索を開始します。
また、何文字目かという順番ですが、これはRubyの配列の添え字と同じく、0文字目から始まりますので注意が必要です。
例えば、”abcdef”というレシーバがあり、”bc”という文字を検索した場合、結果は「1文字目」であり、値「1」の数値が戻値となります。
サンプルコード:
p "abcdef".index("ab") p "abcdef".index("bc") p "abcdef".index("de") p "abcdef".index("z")
サンプルコードの実行結果:
0 1 3 nil
以上のように、文字列”abcdef”をレシーバにしてindexメソッドを実行することによって、indexメソッドの引数に指定した文字列を”abcdef”の中から検索し、検索文字が何文字目の位置に出てくるかを戻値として受け取りました。
検索文字が見つからない場合は、nilが戻値として返ってくることも確認できましたね。
rindexメソッドによる文字列の検索
rindexメソッドも、文字列の中に指定の文字列が含まれているか確かめるメソッドです。
ただし、rindexメソッドは、indexメソッドの逆で、レシーバの文字列の末尾、つまり右側端の文字から左側に向かって検索を開始します。
(rindexは、Reverse(逆) Index の略語です。)
rindexメソッドは、検索文字がレシーバの文字列の中で左から何文字目の位置に出てくるか検索し、その何文字目かを返します。文字が見つからなければnilを返します。
改めて注意が必要なのは、rindexメソッドは、レシーバの文字列の右側から検索を行いますが、戻値は左から何文字目の位置かを返す点です。
右側から何文字目かではないので、注意してください。
また、何文字目かという順番ですが、これもindexと同じく0文字目から始まりますので注意が必要です。
例えば、”abcdef”というレシーバがあり、”bc”という文字を検索した場合、結果は「1文字目」であり、値「1」の数値が戻値となります。
サンプルコード:
p "abcdef".rindex("ab") p "abcdef".rindex("bc") p "abcdef".rindex("de") p "abcdef".rindex("z")
サンプルコードの実行結果:
0 1 3 nil
以上のように、文字列”abcdef”をレシーバにしてrindexメソッドを実行することによって、rindexメソッドの引数に指定した文字列を”abcdef”の中から検索し、検索文字が左から何文字目の位置に出てくるかを戻値として受け取りました。
検索文字が見つからない場合は、nilが戻値として返ってくることも確認できましたね。
include?メソッドによる文字列の検索
indexメソッドやrindexメソッドは、レシーバの文字列を検索し、何文字目の位置に検索文字列が見つかったか数値の値を返していました。
しかし、一般的には、「レシーバの文字列に検索文字が存在するかどうか?」のチェックだけで済む処理も多いです。
そこで、Rubyでは、そのような簡略的な使用法を行うメソッドとして、include?メソッドを用意しています。
include?メソッドは、文字列を検索するメソッドです。
レシーバの文字列に対し、include?メソッドを検索文字列を引数に指定して実行すると、検索文字列がレシーバに見つかった場合はtrueを返し、見つからない場合は、falseを返します。
これだけの機能でも、十分活躍の場面はありますので、ぜひ、この機会に覚えておいてください。
サンプルコード:
p "abcdef".include?("ab") p "abcdef".include?("bc") p "abcdef".include?("de") p "abcdef".include?("z")
サンプルコードの実行結果:
true true true false
以上のように、include?メソッドは、引数の検索文字列がレシーバの文字列内に見つかればtrue、見つからなければfalseを返します。
matchメソッドによる文字列の検索
Rubyの文字列の検索メソッドの最後は、matchメソッドです。
matchメソッドは引数の「正規表現」を使って「パターンマッチ」を行う重要なメソッドです。
正規表現とパターンマッチの概念については、少し高度な内容になるため、ここでは簡単に紹介するだけにしておきます。
読者の皆さんも、機会があられましたら、ぜひ、「正規表現」と「パターンマッチ」について勉強されてくださいね。Rubyの中でも大変重宝されるテクニックです。
ここでは、1個以上の数字とマッチする正規表現/\d+/を例にmatch関数の動きを解説します。
(正規表現は文字列のように記述しますが、文字列オブジェクトとは違うため、”” ではなく // でくくります)
レシーバの文字列が、”SUB-0123-A”というような文字列だったとします。このような文字列は、商品コードなどによく登場しますね。
ここで正規表現/\d+/をmatchの引数に渡して実行すると、パターン「0123」にマッチし、matchメソッドは、マッチしたパターンのMatchDataオブジェクトを返します。
ここでは、MatchDataオブジェクトの添え字0番目のオブジェクトが”0123”となります。
このように、レシーバの文字列の中から、特定のパターンにマッチする文字列を抽出するのが、正規表現の主な役割です。
なお、\d は、数字1文字にマッチする正規表現で、+ は+の直前の文字(ここでは\d、つまり数字)が1個以上並んでいる文字列にマッチする正規表現です。
そのため、/\d+/という正規表現は、数字が1個以上並んでいる文字列にマッチします。
サンプルコード:
m = "SUB-0123-A".match(/\d+/) p m[0] if m m = "ABC-DEF-0909".match(/\d+/) p m[0] if m m = "20170101-NEW".match(/\d+/) p m[0] if m
サンプルコードの実行結果:
"0123" "0909" "20170101"
以上のように、matchメソッドでパターンマッチを行うことにより、目的の「1個以上の数字の文字列」を抽出できていますね。
まとめ
いかがでしたでしょうか。
Rubyの文字列の検索には、いろいろなメソッドがありましたね。
それぞれ用途も使用場面も異なります。
一度に覚えるのは大変ですが、おおまかにこんなメソッドがあるものと覚えておいて、使う場面になった際に復習されるのが良いと思います。
また、ここでは詳細には解説していませんが、Rubyの文字列の操作では、正規表現も必須になってきますので、合わせて確認しておきましょう。
文字列の検索の使い方を忘れたら、またこの記事を読み返してみてください。
Rubyの文字列をしっかり理解したい方に
この記事は文字列を体系的に解説した3ステップで簡単! Rubyの文字列を 完全理解の一部となります。
文字列をさらに理解したい方はこちらを読んでどんどん理解を深めていくようにしましょう。