PerlerのRuby日記

Rubyとか

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"