print("Hello, Ruby.\n")
puts "Hello,\n\tRuby." p "Hello,\n\tRuby."
print "いづれの御時にか女御更衣あまたさぶらいたまいけるなかに\n" print "いとやむごとなき際にはあらぬがすぐれて時めきたまふありけり\n"
x = 10 y = 20 z = 30 area = (x*y + y*z + z*x) * 2 volume = x * y * z print "表面積=", area, "\n" print "体積=", volume, "\n"
=begin
「たのしいRuby 第3版」サンプル
コメントの使い方の例
2006/06/16 作成
2006/07/01 一部コメントを追加
2009/11/01 第3版用に更新
=end
x = 10 # 横
y = 20 # 縦
z = 30 # 高さ
# 表面積と体積を計算する
area = (x*y + y*z + z*x) * 2
volume = x * y * z
# 出力する
print "表面積=", area, "\n"
print "体積=", volume, "\n"
a = 20 if a >= 10 then print "bigger\n" end if a <= 9 then print "smaller\n" end
def hello print "Hello, Ruby\n" end hello()
def hello print "Hello, Ruby.\n" end
require "hello" # hello.rbの読み込み(「.rb」は必要ない) hello() # helloメソッドの起動
print "<html><title>font size list</title>"
print "<body>\n<p>\n"
font_table = {:normal => "+0", :small => "-1", :big => "+1"}
font_table.each do |key, value|
print '<font size="', value, '">',key,'</font><br>',"\n"
end
print "</p></body></html>\n"
names = ["小林", "林", "高野", "森岡"]
names.each do |name|
if /林/ =~ name
puts name
end
end
require "pp"
v = [
{
:key_00 => "「たのしいRuby」",
:key_01 => "「Rubyレシピブック」",
:key_02 => "「Railsレシピブック」",
:key_03 => "「たのしいRuby 第3版」",
}
]
p v
pp v
print "最初の引数: ", ARGV[0], "\n" print "2番目の引数: ", ARGV[1], "\n" print "3番目の引数: ", ARGV[2], "\n"
name = ARGV[0] print "Happy Birthday, ", name, "!\n"
num0 = ARGV[0].to_i num1 = ARGV[1].to_i print num0, " + ", num1, " = ", num0 + num1, "\n" print num0, " - ", num1, " = ", num0 - num1, "\n" print num0, " * ", num1, " = ", num0 * num1, "\n" print num0, " / ", num1, " = ", num0 / num1, "\n"
filename = ARGV[0] file = open(filename) text = file.read print text file.close
filename = ARGV[0] text = File.read(filename) print text
print File.read(ARGV[0])
filename = ARGV[0] file = open(filename) while text = file.gets print text end file.close
pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
3:
file = open(filename)
while text = file.gets
if pattern =~ text
print text
end
end
file.close
$x = 0 x = 0 require "sub" p $x #=> 1 p x #=> 0
$x = 1 ## グローバル変数に代入 x = 1 ## ローカル変数に代入
# 西暦から平成に変換する ad = ARGV[0].to_i heisei = ad - 1988 print heisei,"\n"
a = 10 b = 20 if b > a print "bはaよりも大きい\n" elsif b == a print "bはaと同じ\n" else print "aよりも小さい\n" end
a = 10 b = 20 unless a > b print "aはbより大きくない\n" end
tags = [ "A", "IMG", "PRE" ]
tags.each do |tagname|
case tagname
when "P","A","I","B","BLOCKQUOTE"
print tagname, " has child.\n"
when "IMG", "BR"
print tagname, " has no child.\n"
else
print tagname, " cannot be used.\n"
end
end
array = [ "a", 1, nil ]
array.each do |item|
case item
when String
puts "item is a String."
when Numeric
puts "item is a Numeric."
else
puts "item is something."
end
end
4.times do print "いちめんのなのはな\n" end
5.times do |i| print i,"回目の繰り返しです。\n" end
5.times do |i| print i+1,"回目の繰り返しです。\n" end
sum = 0 for i in 1..5 sum = sum + i end print sum,"\n"
names = ["awk", "Perl", "Python", "Ruby"] for name in names print name,"\n" end
i = 1 while i<3 print i,"\n" i+=1 end
sum = 0 i = 1 while i <= 5 sum += i i += 1 end print sum,"\n"
sum = 0 i = 1 while sum < 50 sum += i i += 1 end print sum,"\n"
sum = 0 i = 1 until sum>=50 sum += i i += 1 end print sum, "\n"
sum = 0 i = 1 while !(sum >= 50) sum += i i += 1 end print sum, "\n"
names = ["awk","Perl","Python","Ruby"] names.each do |name| print name,"\n" end
sum = 0 (1..5).each do |i| sum = sum + i end print sum,"\n"
print "breakの例:\n"
i = 0
["Perl", "Python", "Ruby", "Scheme"].each do |lang|
i += 1
if i == 3
break
end
p [ i, lang ]
end
10:
print "\nnextの例:\n"
i = 0
["Perl", "Python", "Ruby", "Scheme"].each do |lang|
i += 1
if i == 3
next
end
p [ i, lang ]
end
20:
print "\nredoの例:\n"
i = 0
["Perl", "Python", "Ruby", "Scheme"].each do |lang|
i += 1
if i == 3
redo
end
p [ i, lang ]
end
pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
max_matches = 10 # 出力する最大数
matches = 0 # マッチした行数
file = open(filename)
while text = file.gets
if matches >= max_matches
break
end
if pattern =~ text
matches += 1
print text
end
end
file = open(ARGV[0]) while text = file.gets next if /^\s*$/ =~ text # 空白行 next if /^#/ =~ text # シャープで始まる行 print text end
# 10の階乗を求める ans = 1 for i in 1..10 ans *= i end # 出力する print "10! = ", ans, "\n"
ans = 1 for i in 1..10 ans *= i end print "10! = ", ans, "\n"
def hello(name)
print("Hello, ", name, ".\n")
end
hello("Ruby")
def hello(name="Ruby")
print("Hello, ", name, ".\n")
end
hello() # 引数を省略して呼び出す
hello("Newbie") # 引数を指定して呼び出す
class HelloWorld # class文
Version = "1.0" # 定数の定義
def initialize(myname="Ruby") # initializeメソッド
@name = myname # インスタンス変数の初期化
end
def hello # インスタンスメソッド
print "Hello, world. I am ", @name, ".\n"
end
end
bob = HelloWorld.new("Bob")
alice = HelloWorld.new("Alice")
ruby = HelloWorld.new
bob.hello
class HelloCount
@@count = 0 # helloメソッドの呼び出し回数
def HelloCount.count # 呼び出し回数を参照するためのクラスメソッド
@@count
end
def initialize(myname="Ruby")
@name = myname
end
def hello
@@count += 1 # 呼び出し回数を加算する
print "Hello, world. I am ", @name, ".\n"
end
end
bob = HelloCount.new("Bob")
alice = HelloCount.new("Alice")
ruby = HelloCount.new
p HelloCount.count #=> 0
bob.hello
alice.hello
ruby.hello
p HelloCount.count #=> 3
class String
def count_word
ary = self.split(/\s+/) # 自分自身を空白文字で分解する
return ary.size # 分解後の配列の要素数を返す
end
end
str = "Just Another Ruby Newbie"
p str.count_word #=> 4
class AccTest
def pub
puts "pub is a public method."
end
public :pub # pubメソッドをpublicに設定(指定しなくてもよい)
def priv
puts "priv is a private method."
end
private :priv # privメソッドをprivateに設定
end
acc = AccTest.new
acc.pub #=> pub is a public method.
acc.priv #=> エラー
class Point
attr_accessor :x, :y # アクセスメソッドを定義する
protected :x=, :y= # x=とy=をprotectedにする
def initialize(x=0.0, y=0.0)
@x, @y = x, y
end
def swap(other) # x, yの値を入れ換えるメソッド
tmp_x, tmp_y = @x, @y
@x, @y = other.x, other.y
other.x, other.y = tmp_x, tmp_y # 同一クラス内では呼び出すことができる
return self
end
end
p0 = Point.new
p1 = Point.new(1.0, 2.0)
p [ p0.x, p0.y ] #=> [0.0, 0.0]
p [ p1.x, p1.y ] #=> [1.0, 2.0]
p0.swap(p1)
p [ p0.x, p0.y ] #=> [1.0, 2.0]
p [ p1.x, p1.y ] #=> [0.0, 0.0]
p0.x = 10.0 #=> エラー
ring_array.rb
class RingArray < Array # スーパークラスを指定する
def [](i) # 演算子[]の再定義
idx = i % size # 新しいインデックスを求める
super(idx) # スーパークラスの同名のメソッドを呼ぶ
end
end
eto = RingArray[ "子", "丑", "寅", "卯", "辰", "巳",
"午", "未", "申", "酉", "戌", "亥" ]
p eto[6] #=> "午"
p eto[11] #=> "亥"
p eto[15] #=> "卯"
p eto[-1] #=> "亥"
module MyModule # 共通して提供したいメソッドなど end class MyClass1 include MyModule # MyClass1 に固有のメソッドなど end class MyClass2 include MyModule # MyClass2 に固有のメソッドなど end
module HelloModule # module文
Version = "1.0" # 定数の定義
def hello(name) # メソッドの定義
print "Hello, ", name, ".\n"
end
module_function :hello # helloをモジュール関数として公開する
end
p HelloModule::Version #=> "1.0"
HelloModule.hello("Alice") #=> Hello, Alice.
include HelloModule # インクルードしてみる
p Version #=> "1.0"
hello("Alice") #=> Hello, Alice.
def fetch_and_downcase(ary, index)
if str = ary[index]
return str.downcase
end
end
ary = ["Boo", "Foo", "Woo"]
p fetch_and_downcase(ary, 1) #=> "foo"
require "net/http"
url = URI.parse("http://www.ruby-lang.org/ja/")
http = Net::HTTP.start(url.host, url.port)
doc = http.get(url.path)
puts doc
ltotal = 0 # 行数の合計
wtotal = 0 # 単語数の合計
ctotal = 0 # 文字数の合計
ARGV.each do |file|
begin
input = open(file) # ファイルを開く(A)
l = 0 # file内の行数
w = 0 # file内の単語数
c = 0 # file内の文字数
while line = input.gets
l += 1
c += line.size
line.sub!(/^\s+/, "") # 行頭の空白を削除
ary = line.split(/\s+/) # 空白文字で分解する
w += ary.size
end
input.close # ファイルを閉じる
printf("%8d %8d %8d %s\n", l, w, c, file) # 出力を整形する
ltotal += l
wtotal += w
ctotal += c
rescue => ex
print ex.message, "\n" # 例外のメッセージを出力(B)
end
end
printf("%8d %8d %8d %s\n", ltotal, wtotal, ctotal, "total")
def test_throw throw :test end puts "test start" catch(:test) do puts "before test_throw()" test_throw() puts "after test_throw()" end puts "test end"
ファイル名のあるソースコードはありません。
list = ["a", "b", "c", "d"] for i in 0..3 print i+1,"番目の要素は",list[i],"です。\n" end
list = [1, 3, 5, 7, 9] sum = 0 for i in 0..4 sum += list[i] end print "合計:",sum,"\n"
list = [1, 3, 5, 7, 9] sum = 0 list.each do |elem| sum += elem end print "合計:",sum,"\n"
list = ["a", "b", "c", "d"] list.each_with_index do |elem, i| print i+1,"番目の要素は",elem,"です。\n" end
ary1 = [1, 2, 3, 4, 5] ary2 = [10, 20, 30, 40, 50] ary3 = [100, 200, 300, 400, 500] i = 0 result = [] while i < ary1.length result << ary1[i] + ary2[i] + ary3[i] i += 1 end p result #=> [111, 222, 333, 444, 555]
ary1 = [1, 2, 3, 4, 5] ary2 = [10, 20, 30, 40, 50] ary3 = [100, 200, 300, 400, 500] result = [] ary1.zip(ary2, ary3) do |a, b, c| result << a + b + c end p result #=> [111, 222, 333, 444, 555]
ファイル名のあるソースコードはありません。
# 単語数のカウント
2:
count = Hash.new(0)
4:
## 単語の集計
while line = gets
words = line.split
words.each do |word|
count[word] += 1
end
end
12:
## 結果の出力
count.sort{|(k1,v1), (k2,v2)| v1 <=> v2}.each do |key, value|
print "#{key}: #{value}\n"
end
"abracatabra".scan(/.a/) do |matched| p matched end
"abracatabra".scan(/(.)(a)/) do |matched| p matched end
"abracatabra".scan(/(.)(a)/) do |a, b| p a+"-"+b end
str = "http://www.ruby-lang.org/ja/" %r|http://([^/]*)/| =~ str print "server address: ", $1, "\n"
$stdout.print "Output to $stdout.\n" # 標準出力 $stderr.print "Output to $stderr.\n" # 標準エラー出力
if $stdin.tty? print "Stdin is a TTY.\n" else print "Stdin is not a TTY.\n" end
require "open-uri"
# HTTP経由でデータを読み込む
open("http://www.ruby-lang.org") do |io|
puts io.read # Rubyのホームページをコンソールに出力する
end
# FTP経由でデータを読み込む
open("ftp://www.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7.tar.gz") do |io|
open("ruby-1.8.7.tar.gz", "w") do |f| # ローカルファイルを開く
f.write(io.read)
end
end
require "open-uri"
options = {
"Accept-Language" => "ja, en;q=0.5",
}
open("http://www.ruby-lang.org", options){|io|
puts io.read
}
require "stringio"
io = StringIO.new
io.puts("A")
io.puts("B")
io.puts("C")
io.rewind
p io.read #=> "A\nB\nC\n"
require "stringio"
io = StringIO.new("A\nB\nC\n")
p io.gets #=> "A\n"
p io.gets #=> "B\n"
p io.gets #=> "C\n"
$stdout.puts "foo", "bar", "baz"
$stdout.putc(82) # 82は「R」のASCIIコード
$stdout.putc(?R)
$stdout.putc("\n")
$stdout.print "out1 " $stderr.print "err1 " $stdout.print "out2 " $stdout.print "out3 " $stderr.print "err2\n" $stdout.print "out4\n"
$stdout.print "out1 "; $stdout.flush $stderr.print "err1 " $stdout.print "out2 "; $stdout.flush $stdout.print "out3 "; $stdout.flush $stderr.print "err2\n" $stdout.print "out4\n"
$stdout.sync = true # 出力の同期を取る $stdout.print "out1 " $stderr.print "err1 " $stdout.print "out2 " $stdout.print "out3 " $stderr.print "err2\n" $stdout.print "out4\n"
pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
if /.gz$/ =~ filename
file = IO.popen("gunzip -c #{filename}")
else
file = File.open(filename)
end
while text = file.gets do
if pattern =~ text
print text
end
end
def traverse(path)
if FileTest.directory?(path) # ディレクトリの場合
dir = Dir.open(path)
while name = dir.read
next if name == "." # ※
next if name == ".." # ※
traverse(path + "/" + name)
end
dir.close
else
process_file(path) # ファイルに対する処理
end
end
def process_file(path)
puts path # ひとまず出力するだけ
end
traverse(ARGV[0])
def traverse(path)
Dir.glob(["#{path}/**/*", "#{path}/**/.*"]).each do |name|
unless FileTest.directory?(name)
process_file(name)
end
end
end
require 'find'
IGNORES = [ /^\./, /^CVS$/, /^RCS$/ ]
def listdir(top)
Find.find(top) do |path|
if FileTest.directory?(path) # pathがディレクトリならば
dir, base = File.split(path)
IGNORES.each do |re|
if re =~ base # 無視したいディレクトリの場合
Find.prune # それ以下の検索を省略する
end
end
puts path # 出力する
end
end
end
listdir(ARGV[0])
ファイル名のあるソースコードはありません。
puts "$foo: #{$foo}"
puts "$bar: #{$bar}"
puts "$baz: #{$baz}"
class WarningTest
def initialize
@test = "test."
end
def test
print @tset,"\n" ##「@test」を「@tset」と書いている!
end
end
sample_test = WarningTest.new
sample_test.test
dirlist = `dir`
dirlist.each{|line|
if line =~ /.rb$/i
print line
end
}
data = DATA.read print data __END__ ここに書かれている文字は,スクリプトとして解釈 されずに,そのままデータとして使用されます。
# クラスの定義
class Foo
def initialize
puts "foo!!"
end
end
if __FILE__ == $0
Foo.new # サンプルコード
end
hash = {:a=>100, :b=>200, :c=>300}
hash.each_with_index do |(key, value), index|
p [key, value, index]
end
var = 1 # ファイル内のvar
class Foo
var = 2 # クラス定義内のvar
def meth
var = 3 # メソッド定義内のvar
end
end
=== ローカル変数の初期化
ローカル変数は,最初に代入されたときに初期化されます。初期化されていないローカル変数を参照しようとすると例外(NameError)が発生します。
//cmd{
> 【ruby -e 'puts a'】
-e:1: undefined local variable or method `a' for main:Object (NameError)
def local_scope_test(n)
if n > 0
positive = true
elsif n < 0
negative = true
else
zero = true
end
return [positive, negative, zero]
end
p local_scope_test(1)
p local_scope_test(0)
p local_scope_test(-1)
x = 1 # xを初期化 ary = [1, 2, 3] ary.each do |x| # ブロック変数としてxを使用する # … end p x # xの値を確認する
x = y = z = 0 # xとyとzを初期化 ary = [1, 2, 3] ary.each do |x; y| # ブロック変数x,ブロックローカル変数yを使用 y = x # ブロックローカルyを代入 z = x # ブロックローカルでないzを代入 p [x, y, z] # ブロック内のxとyの値を確認する end p [x, y, z] # xとyの値を確認する
class Vector
attr_reader :x, :y
def initialize(x=0, y=0)
@x, @y = x, y
end
def inspect # 表示用
"(#{@x}, #{@y})"
end
def +(other)
Vector.new(@x + other.x, @y + other.y) # x, y のそれぞれを足す
end
def -(other)
Vector.new(@x - other.x, @y - other.y) # x, y のそれぞれを引く
end
end
vec0 = Vector.new(3, 6)
vec1 = Vector.new(1, 8)
p vec0 #=> (3, 6)
p vec1 #=> (1, 8)
p vec0 + vec1 #=> (4, 14)
p vec0 - vec1 #=> (2, -2)
5.times do print "<br>\n" end
print "<br>\n" print "<br>\n" print "<br>\n" print "<br>\n" print "<br>\n"
sum = 0 (1..5).each do |i| sum += i end print "合計: ",sum,"\n"
sum = 0 sum += 1 sum += 2 sum += 3 sum += 4 sum += 5 print "合計: ",sum,"\n"
fruits = ['リンゴ', 'バナナ', 'パイナップル'] fruits.each do |elem| print elem,"\n" end
sum = 0
outcome = {"参加費"=>1000, "ストラップ代"=>1000,"懇親会会費"=>4000}
outcome.each do |item, price|
sum += price
end
print "合計: ",sum,"\n"
sum = 0
outcome = {"参加費"=>1000, "ストラップ代"=>1000,"懇親会会費"=>4000}
outcome.each do |pair|
sum += pair[1] # 値を指定している
end
print "合計: ",sum,"\n"
f = File.open("sample.txt")
f.each do |line|
print line
end
f.close
File.open("sample.txt") do |f|
f.each_line do |line|
print line
end
end
class Book
attr_accessor :title, :author, :genre
def initialize(title, author, genre=nil)
@title = title
@author = author
@genre = genre
end
end
require 'book'
class BookList
## 初期化
def initialize()
@booklist = Array.new
end
## 新しい本を加える
def add(book)
@booklist.push(book)
end
## 本の冊数を返す
def length
@booklist.length
end
## n番目に格納されている本を別の本にする
def []=(n,book)
@booklist[n] = book
end
## n番目に格納されている本を返す
def [](n)
@booklist[n]
end
## 本をリストから削除する
def delete(book)
@booklist.delete(book)
end
end
require 'book'
require 'booklist'
# 本のリストを作る。最初はリストは空になる
booklist = BookList.new
# リストに挿入したい本を用意する
b1 = Book.new("せめて,本格らしく","城平京")
b2 = Book.new("Neo Aqua III","Neo Aqua")
# リストに本を追加する
booklist.add(b1)
booklist.add(b2)
# リストの本を出力する
print booklist[0].title, "\n"
print booklist[1].title, "\n"
pr = Proc.new{
p "a"
}
p "b"
pr.call()
def foo(a, b, &block)
block.call(a, b)
end
foo("a1", "b1"){|a, b|
p a
p b
}
class Book
include Comparable
def <=>(other)
t = @genre.to_s <=> other.genre.to_s # ジャンルを比較する
return t if t != 0 # 違うジャンルならそのまま返す
return @title <=> other.title # タイトルを比較した結果を返す
end
attr_accessor :title, :author, :genre
def initialize(title, author, genre=nil)
@title = title
@author = author
@genre = genre
end
end
require 'book_cmp'
ary = []
ary << Book.new("Software", "Rucker", "SF")
ary << Book.new("BABEL-17", "Delany", "SF")
ary << Book.new("Programming Perl", "Wall", "Computer")
ary << Book.new("Programming Pearls", "Bentley", "Computer")
ary.sort.each{|book|
printf "%-10s %-20s %s\n", book.genre, book.title, book.author
}
require "booklist"
class BookList
include Enumerable
def each
@booklist.each{|book|
yield(book)
}
end
end
require "booklist_enum"
booklist = BookList.new
booklist.add(Book.new("Software", "Rucker", "SF"))
booklist.add(Book.new("BABEL-17", "Delany", "SF"))
booklist.add(Book.new("Programming Perl", "Wall",
"Computer"))
booklist.add(Book.new("Programming Pearls", "Bentley",
"Computer"))
titles = booklist.collect{|book|
book.title
}
p titles
require 'open-uri'
open("http://www.ruby-lang.org/ja/") do |f|
5.times do
print f.gets
end
end
require 'rubygems'
require 'open-uri'
require 'nokogiri'
doc = Nokogiri::HTML(open("http://www.ruby-lang.org/ja/"),nil,'utf-8')
doc.css('h3').each do |h3|
puts h3.text
end
require 'rubygems'
require 'open-uri'
require 'nokogiri'
filename = ARGV[0]
doc = Nokogiri::HTML(open(filename),nil, 'utf-8')
doc.css('h3').each do |h3|
puts h3.text
end
require 'rubygems'
require 'open-uri'
require 'nokogiri'
filename = ARGV[0]
doc = Nokogiri::HTML(open(filename),nil,'utf-8')
doc.css('a').each do |a|
url = URI.parse(a["href"])
if url.host
puts "#{a.text}:#{a["href"]}"
end
end
require 'rss' url = 'http://www.ruby-lang.org/ja/feeds/news.rss' rss = RSS::Parser.parse(url) puts rss.channel.title
require 'rss'
url = 'http://www.ruby-lang.org/ja/feeds/news.rss'
rss = RSS::Parser.parse(url)
rss.items.each do |item|
print item.pubDate.strftime("%Y/%m/%d"),":",item.title,"\n"
end
require 'rubygems'
require 'open-uri'
require 'nokogiri'
require 'rss'
filename = ARGV[0]
doc = Nokogiri::HTML(open(filename),nil,'utf-8')
doc.css('link').each do |link|
if link['type'] == 'application/rss+xml' && link['rel'] == 'alternate'
href = link['href']
url = URI.join(filename, href)
puts "detect: #{url}"
rss = RSS::Parser.parse(url)
rss.items.each do |item|
print item.pubDate.strftime("%Y/%m/%d"),":",item.title,"\n"
end
end
end
文中で使用しているsample-access.logははこちらから取得してください。→sample-access.log
count = 0 # 行数を初期化する
File.open(ARGV[0]) do |io| # ファイルを開く
io.each_line do |line| # 行ごとに処理する
count += 1 # 行数を更新する
end
end
puts count # 行数を表示する
CLF_REGEXP = /
\A (?# 行頭)
(\S+)\s (?# 1 address)
(\S+)\s (?# 2 ident)
(\S+)\s (?# 3 user)
\[([^\]]+)\]\s (?# 4 time)
"(\S+)\s(\S+)\s(\S+)"\s (?# 5 6 7 method url version)
(\d+)\s (?# 8 status)
(\d+|-)\s (?# 9 bytes)
"([^"]*)"\s (?# 10 referer)
"([^"]*)" (?# 11 user_agent)
\Z (?# 行末)
/x
count = 0 # 行数を初期化する
File.open(ARGV[0]) do |io| # ファイルを開く
io.each_line do |line| # 1行ごとに処理する
if CLF_REGEXP =~ line # 正規表現にマッチしたら
p $~.captures # キャプチャした部分を表示する
end
count += 1 # 行数を更新する
end
end
puts count # 行数を表示する
module AccessLog
CLF_REGEXP = /
\A (?# 行頭)
(\S+)\s (?# 1 address)
(\S+)\s (?# 2 ident)
(\S+)\s (?# 3 user)
\[([^\]]+)\]\s (?# 4 time)
"(\S+)\s(\S+)\s(\S+)"\s (?# 5 6 7 method url version)
(\d+)\s (?# 8 status)
(\d+|-)\s (?# 9 bytes)
"([^"]*)"\s (?# 10 referer)
"([^"]*)" (?# 11 user_agent)
\Z (?# 行末)
/x
Entry = Struct.new( # 解析結果を保存するためのクラス
:address, :ident, :user, :time,
:method, :url, :version, :status, :byte,
:referer, :user_agent
)
module_function
def each_entry(file)
file.each_line do |line|
if entry = parse(line)
yield(entry)
end
end
end
def parse(line)
if m = CLF_REGEXP.match(line)
return Entry.new(*m.captures)
end
$stderr.puts("parse failure: #{line.dump}")
return nil
end
end
require "access_log" # access_log.rbを読み込む
count = 0
File.open(ARGV[0]) do |io|
AccessLog.each_entry(io) do |entry|
p entry.to_a # エントリを表示する
count += 1
end
end
puts count
require "access_log"
entries = []
task :load do
logfile = ENV["LOGFILE"] || "access.log" # ログファイル名
puts "loading #{logfile}." # メッセージを表示する
File.open(logfile) do |log| # ログファイルを開いて
AccessLog.each_entry(log) do |entry| # すべてのエントリを読み込む
entries << entry
end
end
end
desc "時間帯別のアクセス数を集計する"
task :time => :load do
hour_count = Hash.new(0) # 集計用のハッシュ
entries.each do |entry| # エントリを順に処理する
times = entry.time.split(/[:\/ ]/) # 時刻を分割する
hour_count[times[3]] += 1 # 「時」のカウントを追加する
end
hours = hour_count.keys.sort # 「時」の一覧を取得する
hours.each do |h| # 集計結果を順に表示する
printf("%s: %s\n", h, "#" * (hour_count[h]/3))
end
end
desc "URL別にアクセス数を集計する"
task :url => :load do
url_count = Hash.new(0) # 集計用のハッシュ
entries.each do |entry| # エントリを順に処理する
url_count[entry.url] += 1 # URLのカウントを追加する
end
ranking = url_count.sort_by{|url, count| -count }
# アクセス数の降順になるようにハッシュの要素をソート
ranking.each do |url, count| # 集計結果を順に表示する
printf("%d: %p\n", count, url)
end
end
desc "エラーになったアクセスを表示する"
task :error => :load do
entries.each do |entry| # エントリを順に処理する
if /^[45]/ =~ entry.status # ステータスが4xxか5xxなら表示する
printf("%p %p %p\n", entry.time, entry.status, entry.url)
end
end
end
task :default => [:time, :error, :url]