Rubyレシピブック050~053途中
050 文字列をバイトごとに処理する
割愛
051 文字列を連結する
なお、短い文字列を大量に追加する場合は、+ではなくString#concatを使うべきです。
なるほど。
Perlは「.」の文字列連結演算子一択だけれど、Rubyは用途によって使い分けが必要らしい。
参照先「060 文字列の末尾に文字列を追加する」にあったベンチマークを手元のマシンでも試してみる。
ただしWindows7にインストールしている1.9.3だ。
plus.rb
buf = "" 50_000.times do buf += "xxx|" end
concat.rb
buf = "" 50_000.times do buf.concat "xxx|" end
$ time /c/Program\ Files\ \(x86\)/Ruby-1.9.3/bin/ruby.exe ~/Desktop/plus.rb real 0m2.886s user 0m0.000s sys 0m0.031s $ time /c/Program\ Files\ \(x86\)/Ruby-1.9.3/bin/ruby.exe ~/Desktop/concat.rb real 0m0.124s user 0m0.000s sys 0m0.031s
約23倍か。Windows版でも挙動は同じだということが確かめられた。
String#concatが破壊的だということも、Yokohama.rbの時に教えてもらえたので、その点だけ注意すれば、基本String#concatで充分なような気もする。
あとその参照先の060が間違った内容だったことも話題になったので書いておく。
concatメソッドと<<演算子の違いは返り値です。concatメソッドは引数を返し、<<演算子はself(追加先の文字列)を返します。
確かに<<演算子はselfというか追加済みの本体の文字列が返ってくるのだけれど、
irb(main):001:0> s = "abc" => "abc" irb(main):002:0> s << "def" => "abcdef"
concatメソッドも同様に追加済みの本体の文字列が返ってくる。引数ではない。
irb(main):001:0> s = "abc" => "abc" irb(main):002:0> s.concat("def") => "abcdef"
ふーむ?
052 文字列の一部を置換する
String#subとString#gsubを使う。
ブロックを渡すと、その中の処理を置換対象検知時に実行してくれる。
Perlのs///eにあたる。
"now now now".gsub(/now/) { sleep 1; Time.now.sec } #=> "54 55 56"
あとは、カッコでのキャプチャがメモリ変数($1,$2の名前も同じだ)で取得できることや、trでの高速置換が行える点もPerlと同じだ。わかりやすい。
053 文字をエスケープする/エスケープを外す
なんかいろいろ正規表現とかURIとかSQLとかで引っかかりそうな記号類をバックスラッシュで「手動で」エスケープする/外す手法が書かれていたけれど、素直にそれ用のメソッド使った方が幸せになれると思う。
Regexp.escape("http://www.google.co.jp/") #=> "http://www\\.google\\.co\\.jp/"
require "uri" URI.escape("? + #") #=> "?%20+%20%23"