LoginSignup
8
8

More than 5 years have passed since last update.

Rubyでtailってみた(ついでにheadも作ってみた)。

Posted at

元記事

Rubyでファイルの末尾n行を表示するtailっぽい何かを作った
tailっぽい何かをレビューしてみます。
tailを実装する

ということで、自分もやってみたら、なぜかこうなった。

tail.rb
#!/usr/bin/env ruby
class IO
  # 現在のposからn行だけ配列で返す。
  # posは読み込んだところまで。
  def head(n)
    lazy.first(n)
  end

  # 現在のposからeofまでのうち終わりn行だけ配列で返す。
  # posはeofになる。
  def tail(n)
    reverse_each.lazy.first(n).reverse
  end
end

if $0 == __FILE__
  filename = ARGV[0]
  size = ARGV[1].to_i
  open(filename) do |io|
    io.tail(size).each do |line|
      print line
    end
  end
end

どんな感じかというと。

  1. tailだけなんてかわいそう、headも実装してあげないと!
  2. やっぱ、オブジェクト指向っぽくIO#tail(n)って感じで呼び出したいよね!
  3. 時代は関数型プログラミング!ということでlazy。tailの方の実装でlazyする意味は?とか聞かないで。たぶん、lazyのほうがちょっとだけ速い(気がする)。
  4. シークとかファイルサイズとか調べるの面倒だから、全部読み込んでもいいんじゃね?そもそもIO#sizeないし。メモリ喰い過ぎじゃ無いかって?Rubyでメモリを気にしたら、負けだと思っている。

と、なっております。

ファイルシステムやサイズによりますけど、ファイルのシークは結構高コストです。それに比べて、シーケンシャルアクセスだとバッファとかもあってかなり高速ってのもあるので、数MB程度なら何も考えずに全部取った方が速いかもです。でも、さすがにGB級だと上では対応できないので、io.tail(n)する前にio.seek(-(n * 1024), IO::SEEK_END)とかすべきかな。

8
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8