Rubyコーディングあれこれ (初めての方むけ: 正規表現の比較式で #{} の使い方)
本地震の予測マップ・プログラムの開発言語は Ruby なのですが、以前から初めての方むけにコーディングテクをまとめておければ、と考えていました。 そこで思い付くままにまとめてみよう、と考えております。
今回は、正規表現で比較式に #{} を使う場合の注意です。 (短くまとめます)
前回、正規表現の比較式で #{} を使う例を上げましたが[1]、不十分でしたのでここに追加します。
変数 str に比較したい文字列が格納されているとして:
compare = /#{str}/
として比較式に #{str} を埋め込む場合は多いかと思います。 ですが、ここで str に特殊制御文字が在ると思いどうりには動きません(特殊制御文字として解釈されるので、当然です)。
\ [ ] . ^ $ ? * + { } | ( ) です。
これらの文字を通常の文字として認識したい場合ですが、エスケープ指示 "\" を各特殊制御文字の前段にかませる必要があります。
これには色々なやり方があると思いますが .gsub を使って一気に変更するやり方は簡単です。
どのような特殊制御文字が入っているのか分かっていれば(例えば [ ] の場合):
temp = str.gsub(/\[/, "\\[") # [ を \[ にすべて変更 ( \\ と2個必要)。
temp = temp.gsub(/\]/, "\\]") # その後 ] を \] にすべて変更 ( \\ と2個必要)。
と二回に分けて [ ] を変更します。
これを必要に応じて temp をドンドン変更するチェインすれば大抵大丈夫です。
しかし汎用にやりたいという場合はこれでは駄目です(やり方が弱すぎます)。 私の場合は、 StringScanner を無限ループ内に入れるやり方で対処しています。 が、ここでは長くなるので止めておきます。 ループ内に StringScanner を入れるやり方は別途まとめます。
尚、特殊制御文字ではない特殊文字で # % & ! @ 等は "\" を前置する必要はありませんので、データベースのストリングアイテムに属性を持たせたい場合、これらの文字をアタッチさせておくと便利です。 正規表現での探索も楽ですし、 .gsub を使っての変更も楽になります。
又、 .gsub を使って文字列を一気に変更する場合ですが、文字列が数十万文字を超えるような場合に一気に変更しようとすると、かなり時間がかかってしまう場合があります。 文字数が増殖する場合に時間がかかり出すケースが多いように感じています。 .gsub(/abc/, "xyz") は大丈夫ですが、 .gsub(/abc/, "pqrxyz") は出現頻度が多いと時間がかかる、という意味です。
.gsub で長い文字列を扱う場合は注意が必要です。
以上です。