challenge tailの実装

'tail'を実装してください。

巨大なファイルでも効率的に動作するようにしてください。

最低限必要な機能は、

  • 行数指定
  • 「-f」パラメータの対応

です。

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

Index

Feed

Other

Link

Pathtraq

loading...