tailの実装
Posted feedbacks - Ruby
Rubyもまだの様なので書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | #! /usr/bin/ruby
class Tail
BUF_SIZE = 4096
attr_accessor :lines, :follow, :file, :quit, :_f
private :_f
def initialize(lines,follow,file)
self.lines = lines ? lines.to_i : 10
self.follow = follow ? follow : false
self.file = file
quit = false
self.send(:_f=,File.open(file,'r').binmode)
self
end
def _tailn
lines = self.lines
size = _f.lstat.size
pos = size
tail = ''
tails = []
until(pos <= 0) do
buf = ''
if pos < BUF_SIZE
_f.pos = 0
buf = _f.read(pos)
else
_f.pos = pos - BUF_SIZE
buf = _f.read(BUF_SIZE)
end
raise IOError.new('cannot read file.') unless(buf)
pos -= buf.size
tail = buf + tail
break if tail.split(/(?:\x0d\x0a|\x0d|\x0a)/).size > lines
end
tail = tail.gsub(/(\x0d\x0a|\x0d|\x0a)/,"\n")
tails = tail.split(/\n/)
tails.push("") if tail =~ /\n\z/
print tails.reverse.first(lines).reverse.join("\n")
STDOUT.flush
_f.pos = size
self
end
def _tailf
until(quit) do
buf = ''
buf = _f.read
raise IOException.new('cannot read file.') unless(buf)
if (buf.size > 0)
buf = buf.gsub(/(\x0d\x0a|\x0d|\x0a)/,"\n")
print buf
STDOUT.flush
end
sleep(1)
end
self
end
def tail
_tailn
_tailf if follow
end
def finalize
_f.close
end
end
require "optparse"
tail = nil
conf = Hash.new
opts = OptionParser.new
opts.on("-n MANDATORY") { |v| conf[:n] = v }
opts.on("-f") { |v| conf[:f] = v }
opts.parse!
if ARGV.size == 0
puts "usage: ruby #{$0} [-n lines] [-f] filename"
else
begin
tail = Tail.new(conf[:n],conf[:f],ARGV.shift)
Signal.trap(:INT) { tail.quit = true }
tail.tail
tail.finalize
rescue => e
puts e.message
end
end
|

takeru #6818() Rating-9/11=-0.82
'tail'を実装してください。
巨大なファイルでも効率的に動作するようにしてください。
最低限必要な機能は、
です。
[ reply ]