|第 1 章|
|第 2 章|
|第 3 章|
|第 4 章|
|第 5 章|
|第 6 章|
|第 7 章|
|第 8 章|
|第 9 章|
|第 10 章|
|第 11 章|
|第 12 章|
|第 13 章|
|第 14 章|
|第 15 章|
|第 16 章|
|第 17 章|
|第 18 章|
|第 19 章|
|第 20 章|
|第 21 章|
|第 22 章|
|第 23 章|
第 1 章
代码清单 1.1:helloruby.rb
| 1
 | print("Hello, Ruby.\n")
 | 
  
代码清单 1.2:put_and_p.rb
| 1
2
 | puts "Hello,\n\tRuby."
p "Hello,\n\tRuby."
 | 
  
代码清单 1.3:kiritsubo.rb
| 1
2
 | print "话说从前某一朝天皇时代,后宫妃嫔甚多,\n"
print "其中有一更衣,出身并不十分高贵,却蒙皇上特别宠爱\n"
 | 
  
代码清单 1.4:area_volume.rb
| 1
2
3
4
5
6
7
 | x = 10
y = 20
z = 30
area = (x*y + y*z + z*x) * 2
volume = x * y * z
print "表面积=", area, "\n"
print "体积=", volume, "\n"
 | 
  
代码清单 1.5:comment_sample.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 | =begin
《Ruby基础教程》第4版例子
注释的使用例子
2006/06/16 创建
2006/07/01 追加一部分注释
2013/04/01 第4版更新
=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"
 | 
  
代码清单 1.6:bigger_smaller.rb
| 1
2
3
4
5
6
7
 | a = 20
if a >= 10 then
  print "bigger\n"
end
if a <= 9 then
  print "smaller\n"
end
 | 
  
第 2 章
无代码清单。
第 3 章
代码清单 3.1:print_argv.rb
| 1
2
3
 | puts "首个参数: #{ARGV[0]}"
puts "第2个参数: #{ARGV[1]}"
puts "第3个参数: #{ARGV[2]}"
 | 
  
代码清单 3.2:happy_birth.rb
| 1
2
 | name = ARGV[0]
print "Happy Birthday, ", name, "!\n"
 | 
  
代码清单 3.3:arg_arith.rb
| 1
2
3
4
5
6
 | num0 = ARGV[0].to_i
num1 = ARGV[1].to_i
puts "#{num0} + #{num1} = #{num0 + num1}"
puts "#{num0} - #{num1} = #{num0 - num1}"
puts "#{num0} * #{num1} = #{num0 * num1}"
puts "#{num0} / #{num1} = #{num0 / num1}"
 | 
  
代码清单 3.4:read_text.rb
| 1
2
3
4
5
 | filename = ARGV[0]
file = File.open(filename) # ①
text = file.read           # ②
print text                 # ③
file.close                 # ④
 | 
  
代码清单 3.5:read_text_simple.rb
| 1
2
3
 | filename = ARGV[0]
text = File.read(filename)
print text
 | 
  
代码清单 3.6:read_text_oneline.rb
| 1
 | print File.read(ARGV[0])
 | 
  
代码清单 3.7:read_line.rb
| 1
2
3
4
5
6
 | filename = ARGV[0]
file = File.open(filename)
file.each_line do |line|
  print line
end
file.close
 | 
  
代码清单 3.8:simple_grep.rb
| 1
2
3
4
5
6
7
8
9
10
 | pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
file = File.open(filename)
file.each_line do |line|
  if pattern =~ line
    print line
  end
end
file.close
 | 
  
代码清单 3.9:hello_ruby2.rb
| 1
2
3
4
5
 | def hello
  puts "Hello, Ruby"
end
hello()
 | 
  
代码清单 3.10:grep.rb
| 1
2
3
4
5
6
7
8
9
 | def simple_grep(pattern, filename)
  file = File.open(filename)
  file.each_line do |line|
    if pattern =~ line
      print line
    end
  end
  file.close
end
 | 
  
代码清单 3.11:use_grep.rb
| 1
2
3
4
5
 | require "./grep"                # 读取grep.rb(省略“.rb”)
pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
simple_grep(pattern, filename)  # 调用simple_grep方法
 | 
  
代码清单 专栏:p_and_pp.rb
| 1
2
3
4
5
6
7
8
9
 | require "pp"
v = [{
      key00: "《Ruby基础教程 第4版》",
      key01: "《Ruby秘笈》",
      key02: "《Rails3秘笈》"
    }]
p v
pp v
 | 
  
第 4 章
代码清单 4.1:scopetest.rb
| 1
2
3
4
5
6
7
 | $x = 0
x = 0
require "./sub"
p $x   #=> 1
p x    #=> 0
 | 
  
代码清单 4.2:sub.rb
| 1
2
 | $x = 1  ## 对全局变量赋值
x = 1   ## 对局部变量赋值
 | 
  
第 5 章
代码清单 5.1:ad2heisei.rb
| 1
2
3
4
5
6
 | #将西历转换为平成纪年
ad = ARGV[0].to_i
heisei = ad - 1988
puts heisei
 | 
  
代码清单 5.2:if_elsif.rb
| 1
2
3
4
5
6
7
8
9
 | a = 10
b = 20
if a > b
  puts "a比b大"
elsif a < b
  puts "a比b小"
else
  puts "a与b相等"
end
 | 
  
代码清单 5.3:unless.rb
| 1
2
3
4
5
 | a = 10
b = 20
unless a > b
  puts "a不比b大"
end
 | 
  
代码清单 5.4:case.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
 | tags = [ "A", "IMG", "PRE" ]
tags.each do |tagname|
  case tagname
  when "P","A","I","B","BLOCKQUOTE"
    puts "#{tagname} has child."
  when "IMG", "BR"
    puts "#{tagname} has no child."
  else
    puts "#{tagname} cannot be used."
  end
end
 | 
  
代码清单 5.5:case_class.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
 | 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
 | 
  
第 6 章
代码清单 6.1:times.rb
| 1
2
3
 | 7.times do
  puts "满地油菜花"
end
 | 
  
代码清单 6.2:times2.rb
| 1
2
3
 | 5.times do |i|
  puts "第#{i}次的循环。"
end
 | 
  
代码清单 6.3:times3.rb
| 1
2
3
 | 5.times do |i|
  puts "第#{i+1}次的循环。"
end
 | 
  
代码清单 6.4:for.rb
| 1
2
3
4
5
 | sum = 0
for i in 1..5
  sum = sum + i
end
puts sum
 | 
  
代码清单 6.5:for_names.rb
| 1
2
3
4
 | names = ["awk", "Perl", "Python", "Ruby"]
for name in names
  puts name
end
 | 
  
代码清单 6.6:while.rb
| 1
2
3
4
5
 | i = 1
while i < 3
  puts i
  i += 1
end
 | 
  
代码清单 6.7:while2.rb
| 1
2
3
4
5
6
7
 | sum = 0
i = 1
while i <= 5
  sum += i
  i += 1
end
puts sum
 | 
  
代码清单 6.8:while3.rb
| 1
2
3
4
5
6
7
 | sum = 0
i = 1
while sum < 50
  sum += i
  i += 1
end
puts sum
 | 
  
代码清单 6.9:until.rb
| 1
2
3
4
5
6
7
 | sum = 0
i = 1
until sum >= 50
  sum += i
  i+= 1
end
puts sum
 | 
  
代码清单 6.10:while_not.rb
| 1
2
3
4
5
6
7
 | sum = 0
i = 1
while !(sum >= 50)
  sum += i
  i += 1
end
puts sum
 | 
  
代码清单 6.11:each_names.rb
| 1
2
3
4
 | names = ["awk","Perl","Python","Ruby"]
names.each do |name|
  puts name
end
 | 
  
代码清单 6.12:each.rb
| 1
2
3
4
5
 | sum = 0
(1..5).each do |i|
  sum= sum + i
end
puts sum
 | 
  
代码清单 6.13:break_next_redo.rb
| 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
 | puts "break的例子:"
i = 0
["Perl", "Python", "Ruby", "Scheme"].each do |lang|
  i += 1
  if i == 3
    break
  end
  p [i,lang]
end
puts "next的例子:"
i = 0
["Perl", "Python", "Ruby", "Scheme"].each do |lang|
  i += 1
  if i == 3
    next
  end
  p [i,lang]
end
puts "redo的例子:"
i = 0
["Perl", "Python", "Ruby", "Scheme"].each do |lang|
  i += 1
  if i == 3
    redo
  end
  p [i,lang]
end
 | 
  
代码清单 6.14:ten_lines_grep.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
max_matches = 10      # 输出的最大行数
matches = 0           # 已匹配的行数
file = File.open(filename)
file.each_line do |line|
  if matches >= max_matches
    break
  end
  if pattern =~ line
    matches += 1
    puts line
  end
end
file.close
 | 
  
代码清单 6.15:strip.rb
| 1
2
3
4
5
6
7
 | file = File.open(ARGV[0])
file.each_line do |line|
  next if /^\s*$/ =~ line  # 空行
  next if /^#/ =~ line     # 以“#”开头的行
  puts line
end
file.close
 | 
  
代码清单 6.16:fact.rb
| 1
2
3
4
5
6
7
8
 | # 求10的阶乘
ans = 1
for i in 1..10
  ans *= i
end
# 输出
puts "10! = #{ans}"
 | 
  
代码清单 6.17:stripped_fact.rb
| 1
2
3
4
5
 | ans = 1
for i in 1..10
  ans *= i
end
puts "10! = #{ans}"
 | 
  
第 7 章
代码清单 7.1:times_with_param.rb
| 1
2
3
 | 5.times do |i|
  puts "第#{i}次循环。"
end
 | 
  
代码清单 7.2:hello_with_name.rb
| 1
2
3
4
5
 | def hello(name)
  puts "Hello, #{name}."
end
hello("Ruby")
 | 
  
代码清单 7.3:hello_with_default.rb
| 1
2
3
4
5
6
 | def hello(name="Ruby")
  puts "Hello, #{name}."
end
hello()         # 省略参数的调用
hello("Newbie") # 指定参数的调用
 | 
  
代码清单 7.4:myloop.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
 | def myloop
  while true
    yield               # 执行块
  end
end
num = 1                 # 初始化num
myloop do
  puts "num is #{num}"  # 输出num
  break if num > 100    # num超过100时跳出循环
  num *= 2              # num乘2
end
 | 
  
第 8 章
代码清单 8.1:hello_class.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | class HelloWorld                   # class语句
  def initialize(myname = "Ruby")  # initialize方法
    @name = myname                 # 初始化实例变量
  end
  def hello                        # 实例方法
    puts "Hello, world. I am #{@name}."
  end
end
bob = HelloWorld.new("Bob")
alice = HelloWorld.new("Alice")
ruby = HelloWorld.new
bob.hello
 | 
  
代码清单 8.2:hello_class2(部分).rb
| 1
2
3
4
5
6
7
8
9
10
11
 | class HelloWorld
  ...
  def name          # 获取@name
    @name
  end
  def name=(value)  # 修改@name
    @name = value
  end
  ...
end
 | 
  
代码清单 8.3:hello_class3(部分).rb
| 1
2
3
4
5
6
7
8
 | class HelloWorld
  attr_accessor :name
  ...
  def greet
    puts "Hi, I am #{self.name}."
  end
end
  ...
 | 
  
代码清单 8.4:hello_count.rb
| 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
 | class HelloCount
  @@count = 0           # 调用hello方法的次数
  def HelloCount.count  # 读取调用次数的类方法
    @@count
  end
  def initialize(myname="Ruby")
    @name = myname
  end
  def hello
    @@count += 1        # 累加调用次数
    puts "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
 | 
  
代码清单 8.5:acc_test.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 | 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
acc.priv
 | 
  
代码清单 8.6:point.rb
| 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
 | 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              #=> 错误(NoMethodError)
 | 
  
代码清单 8.7:ext_string.rb
| 1
2
3
4
5
6
7
8
9
 | class String
  def count_word
    ary = self.split(/\s+/) # 用空格分割接收者
    return ary.size         # 返回分割后的数组的元素总数
  end
end
str = "Just Another Ruby Newbie"
p str.count_word            #=> 4
 | 
  
代码清单 8.8:ring_array.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
 | class RingArray < Array  # 指定父类
  def [](i)              # 重定义运算符[]
    idx = i % size       # 计算新索引值
    super(idx)           # 调用父类中同名的方法
  end
end
wday = RingArray["日", "月", "火", "水", "木", "金", "土"]
wday = RingArray["日", "月", "火", "水", "木", "金", "土"]
p wday[6]   #=> "土"
p wday[11]  #=> "木"
p wday[15]  #=> "月"
p wday[-1]  #=> "土"
 | 
  
代码清单 8.9:mixin_sample.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
 | module MyModule
  # 希望提供的共通方法等
end
class MyClass1
  include MyModule
  # MyClass1中特有的方法等
end
class MyClass2
  include MyModule
  # MyClass2中特有的方法等
end
 | 
  
代码清单 8.10:hello_module.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 | module HelloModule          # module关键字
  Version = "1.0"           # 定义常量
  def hello(name)           # 定义方法
    puts "Hello, #{name}."
  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.
 | 
  
代码清单 8.11:mixin_test.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
 | module M
  def meth
    "meth"
  end
end
class C
  include M  # 包含M模块
end
c = C.new
p c.meth     #=> meth
 | 
  
代码清单 8.12:fetch_and_downcase.rb
| 1
2
3
4
5
6
7
8
 | 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"
 | 
  
代码清单 8.13:http_get.rb
| 1
2
3
4
5
6
 | require "net/http"
require "uri"
url = URI.parse("http://www.ruby-lang.org/ja/")
http = Net::HTTP.start(url.host, url.port)
doc = http.get(url.path)
puts doc
 | 
  
第 9 章
代码清单 9.1:point.rb
| 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
 | class Point
  attr_reader :x, :y
  def initialize(x=0, y=0)
    @x, @y = x, y
  end
  def inspect  # 用于显示
    "(#{x}, #{y})"
  end
  def +(other)  # x、y分别进行加法运算
    self.class.new(x + other.x, y + other.y)
  end
  def -(other)  # x、y分别进行减法运算
    self.class.new(x - other.x, y - other.y)
  end
end
point0 = Point.new(3, 6)
point1 = Point.new(1, 8)
p point0           #=> (3, 6)
p point1           #=> (1, 8)
p point0 + point1  #=> (4, 14)
p point0 - point1  #=> (2, -2)
 | 
  
代码清单 9.2:point1(部分).rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 | class Point
  ...
  def +@
    dup                     # 返回自己的拷贝
  end
  def -@
    self.class.new(-x, -y)  # 颠倒x、y各自的正负
  end
  def ~@
    self.class.new(-y, x)   # 使坐标翻转90度
  end
end
point = Point.new(3, 6)
p +point  #=> (3, 6)
p -point  #=> (-3, -6)
p ~point  #=> (-6, 3)
 | 
  
代码清单 9.3:point2(部分).rb
| 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
 | class Point
  ...
  def [](index)
    case index
    when 0
      x
    when 1
      y
    else
      raise ArgumentError, "out of range `#{index}'"
    end
  end
  def []=(index, val)
    case index
    when 0
      self.x = val
    when 1
      self.y = val
    else
      raise ArgumentError, "out of range `#{index}'"
    end
  end
end
point = Point.new(3, 6)
p point[0]           #=> 3
p point[1] = 2       #=> 2
p point[1]           #=> 2
p point[2]           #=>错误(ArgumentError)
 | 
  
第 10 章
代码清单 10.1:wc.rb
| 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
 | ltotal=0                             # 行数合计
wtotal=0                             # 单词数合计
ctotal=0                             # 字数合计
ARGV.each do |file|
  begin
    input = File.open(file)          # 打开文件(A)
    l=0                              # file内的行数
    w=0                              # file内的单词数
    c=0                              # file内的字数
    input.each_line do |line|
      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")
 | 
  
代码清单 copy:cp.rb
| 1
2
3
4
5
6
7
8
9
10
11
 |     def copy(from, to)
      src = File.open(from)         # 打开原文件from(A)
      begin
        dst = File.open(to, "w")    # 打开目标文件to(B)
        data = src.read
        dst.write(data)
        dst.close
      ensure
        src.close                   # (C)
      end
    end
 | 
  
第 11 章
代码清单 11.1:hash_each.rb
| 1
2
3
4
5
6
 | sum = 0
outcome = {"参加费"=>1000, "挂件费用"=>1000, "联欢会费用"=>4000}
outcome.each do |pair|
  sum += pair[1]  # 指定值
end
puts "合计:#{sum}"
 | 
  
代码清单 11.2:hash_each2.rb
| 1
2
3
4
5
6
 | sum = 0
outcome = {"参加费"=>1000, "挂件费用"=>1000, "联欢会费用"=>4000}
outcome.each do |item, price|
  sum += price
end
puts "合计:#{sum}"
 | 
  
代码清单 11.3:file_each.rb
| 1
2
3
4
5
 | file = File.open("sample.txt")
file.each_line do |line|
  print line
end
file.close
 | 
  
代码清单 11.4:file_open.rb
| 1
2
3
4
5
 | File.open("sample.txt") do |file|
  file.each_line do |line|
    print line
  end
end
 | 
  
代码清单 11.5:file_open_no_block.rb
| 1
2
3
4
5
6
7
8
 | file = File.open("sample.txt")
begin
  file.each_line do |line|
    print line
  end
ensure
  file.close
end
 | 
  
代码清单 11.6:sort_comp_count.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | ary = %w(
  Ruby is a open source programming language with a focus
  on simplicity and productivity. It has an elegant syntax
  that is natural to read and easy to write
)
call_num = 0    # 块的调用次数
sorted = ary.sort do |a, b|
  call_num += 1 # 累加块的调用次数
  a.length <=> b.length
end
puts "排序结果 #{sorted}"
puts "数组的元素数量 #{ary.length}"
puts "调用块的次数 #{call_num}"
 | 
  
代码清单 11.7:myloop.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
 | def myloop
  while true
    yield               # 执行块
  end
end
num = 1                 # 初始化num
myloop do
  puts "num is #{num}"  # 输出num
  break if num > 100    # num超过100后跳出循环
  num *= 2              # num乘2
end
 | 
  
代码清单 11.8:total.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
 | def total(from, to)
  result = 0                # 合计值
  from.upto(to) do |num|    # 处理从from到to的值
    if block_given?         #   如果有块的话
      result += yield(num)  #     累加经过块处理的值
    else                    #   如果没有块的话
      result += num         #     直接累加
    end
  end
  return result             # 返回方法的结果
end
p total(1, 10)                  # 从1到10的和 => 55
p total(1, 10){|num| num ** 2 } # 从1到10的2次冥的和 => 385
 | 
  
代码清单 11.9:block_args_test.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 | def block_args_test
  yield()             # 0个块变量
  yield(1)            # 1个块变量
  yield(1, 2, 3)      # 3个块变量
end
puts "通过|a|接收块变量"
block_args_test do |a|
  p [a]
end
puts
puts "通过|a, b, c|接收块变量"
block_args_test do |a, b, c|
  p [a, b, c]
end
puts
puts "通过|*a|接收块变量"
block_args_test do |*a|
  p [a]
end
puts
 | 
  
代码清单 11.10:param_grouping.rb
| 1
2
3
4
 | hash = {a: 100, b: 200, c: 300}
hash.each_with_index do |(key, value), index|
  p [key, value, index]
end
 | 
  
代码清单 11.11:proc1.rb
| 1
2
3
4
5
6
 | hello = Proc.new do |name|
  puts "Hello, #{name}."
end
hello.call("World")
hello.call("Ruby")
 | 
  
代码清单 11.12:total2.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | def total2(from, to, &block)
  result = 0               # 合计值
  from.upto(to) do |num|   # 处理从from到to的值
    if block               #   如果有块的话
      result +=            #     累加经过块处理的值
           block.call(num)
    else                   #   如果没有块的话
      result += num        #     直接累加
    end
  end
  return result            # 返回方法的结果
end
p total2(1, 10)                   # 从1到10的和 => 55
p total2(1, 10){|num| num ** 2 }  # 从1到10的2次冥的和 => 385
 | 
  
代码清单 11.13:call_each.rb
| 1
2
3
4
5
6
7
 | def call_each(ary, &block)
  ary.each(&block)
end
call_each [1, 2, 3] do |item|
  p item
end
 | 
  
代码清单 11.14:local_and_block.rb
| 1
2
3
4
5
6
7
8
9
 | x = 1            # 初始化x
y = 1            # 初始化y
ary = [1, 2, 3]
ary.each do |x|  # 将x作为块变量使用
  y = x          # 将x赋值给y
end
p [x, y]         # 确认x与y的值
 | 
  
代码清单 11.15:local_and_block2.rb
| 1
2
3
4
5
6
7
8
9
 | 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、z的值
end
puts
p [x, y, z]         # 确认x、y、z的值
 | 
  
第 12 章
无代码清单。
第 13 章
代码清单 13.1:list.rb
| 1
2
3
4
 | list = ["a", "b", "c", "d"]
for i in 0..3
  print "第", i+1,"个元素是",list[i],"。\n"
end
 | 
  
代码清单 13.2:sum_list.rb
| 1
2
3
4
5
6
 | list = [1, 3, 5, 7, 9]
sum = 0
for i in 0..4
  sum += list[i]
end
print "合计:",sum,"\n"
 | 
  
代码清单 13.3:sum_list2.rb
| 1
2
3
4
5
6
 | list = [1, 3, 5, 7, 9]
sum = 0
list.each do |elem|
  sum += elem
end
print "合计:",sum,"\n"
 | 
  
代码清单 13.4:list2.rb
| 1
2
3
4
 | list = ["a", "b", "c", "d"]
list.each_with_index do |elem, i|
  print "第", i+1,"个元素是",elem,"。\n"
end
 | 
  
代码清单 13.5:sum_with_each.rb
| 1
2
3
4
5
6
7
8
9
10
11
 | 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]
 | 
  
代码清单 13.6:sum_with_zip.rb
| 1
2
3
4
5
6
7
8
9
 | 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]
 | 
  
第 14 章
无代码清单。
第 15 章
代码清单 15.1:word_count.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 | # 计算单词数量
count = Hash.new(0)
## 统计单词
File.open(ARGV[0]) do |f|
  f.each_line do |line|
    words = line.split
    words.each do |word|
      count[word] += 1
    end
  end
end
## 输出结果
count.sort{|a, b|
  a[1] <=> b[1]
}.each do |key, value|
  print "#{key}: #{value}\n"
end
 | 
  
第 16 章
代码清单 16.1:scan1.rb
| 1
2
3
 | "abracatabra".scan(/.a/) do |matched|
  p matched
end
 | 
  
代码清单 16.2:scan2.rb
| 1
2
3
 | "abracatabra".scan(/(.)(a)/) do |matched|
  p matched
end
 | 
  
代码清单 16.3:scan3.rb
| 1
2
3
 | "abracatabra".scan(/(.)(a)/) do |a, b|
  p a+"-"+b
end
 | 
  
代码清单 16.4:url_match.rb
| 1
2
3
 | str = "http://www.ruby-lang.org/ja/"
%r|http://([^/]*)/| =~ str
print "server address: ", $1, "\n"
 | 
  
第 17 章
代码清单 17.1:out.rb
| 1
2
 | $stdout.print "Output to $stdout.\n"  # 标准输出
$stderr.print "Output to $stderr.\n"  # 标准错误输出
 | 
  
代码清单 17.2:tty.rb
| 1
2
3
4
5
 | if $stdin.tty?
  print "Stdin is a TTY.\n"
else
  print "Stdin is not a TTY.\n"
end
 | 
  
代码清单 17.3:stdout_put.rb
| 1
 | $stdout.puts "foo", "bar", "baz"
 | 
  
代码清单 17.4:stdout_putc.rb
| 1
2
3
 | $stdout.putc(82)  # 82是“R”的ASCII码
$stdout.putc("Ruby")
$stdout.putc("\n")
 | 
  
代码清单 17.5:test_buffering1.rb
| 1
2
3
4
5
6
 | $stdout.print "out1 "
$stderr.print "err1 "
$stdout.print "out2 "
$stdout.print "out3 "
$stderr.print "err2\n"
$stdout.print "out4\n"
 | 
  
代码清单 17.6:test_buffering2.rb
| 1
2
3
4
5
6
 | $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"
 | 
  
代码清单 17.7:test_buffering3.rb
| 1
2
3
4
5
6
7
 | $stdout.sync = true  # 同步输出处理
$stdout.print "out1 "
$stderr.print "err1 "
$stdout.print "out2 "
$stdout.print "out3 "
$stderr.print "err2\n"
$stdout.print "out4\n"
 | 
  
代码清单 17.8:simple_grep_gz.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
 | pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
if /.gz$/ =~ filename
  file = IO.popen("gunzip -c #{filename}")
else
  file = File.open(filename)
end
file.each_line do |text|
  if pattern =~ text
    print text
  end
end
 | 
  
代码清单 17.9:read_uri.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
 | require "open-uri"
# 通过HTTP读取数据
open("http://www.ruby-lang.org") do |io|
  puts io.read  # 将Ruby的官方网页输出到控制台
end
# 通过FTP读取数据
url = "ftp://www.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p0.tar.gz"
open(url) do |io|
  open("ruby-2.0.0-p0.tar.gz", "w") do |f|  # 打开本地文件
    f.write(io.read)
  end
end
 | 
  
代码清单 17.10:read_uri_ja.rb
| 1
2
3
4
5
6
7
8
 | require "open-uri"
options = {
  "Accept-Language" => "ja, en;q=0.5",
}
open("http://www.ruby-lang.org", options){|io|
  puts io.read
}
 | 
  
代码清单 17.11:stringio_puts.rb
| 1
2
3
4
5
6
7
8
 | require "stringio"
io = StringIO.new
io.puts("A")
io.puts("B")
io.puts("C")
io.rewind
p io.read  #=> "A\nB\nC\n"
 | 
  
代码清单 17.12:stringio_gets.rb
| 1
2
3
4
5
6
 | require "stringio"
io = StringIO.new("A\nB\nC\n")
p io.gets  #=> "A\n"
p io.gets  #=> "B\n"
p io.gets  #=> "C\n"
 | 
  
第 18 章
代码清单 18.1:traverse.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 | def traverse(path)
  if File.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])
 | 
  
代码清单 18.2:traverse_by_glob.rb
| 1
2
3
4
5
6
7
 | def traverse(path)
  Dir.glob(["#{path}/**/*", "#{path}/**/.*"]).each do |name|
    unless File.directory?(name)
      process_file(name)
    end
  end
end
 | 
  
代码清单 18.3:listdir.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 | 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])
 | 
  
第 19 章
代码清单 19.1:utf8mac.rb
| 1
2
3
4
5
6
7
 | # encoding: utf-8
Dir.glob("*.txt") do |filename|
  if filename == "ルビー.txt"
    puts "found."; exit
  end
end
puts "not found."
 | 
  
代码清单 19.2:utf8mac_fix.rb
| 1
2
3
4
5
6
7
 | # encoding: utf-8
Dir.glob("*.txt") do |filename|
  if filename.encode("UTF8-MAC") == "ルビー.txt".encode("UTF8-MAC")
    puts "found."; exit
  end
end
puts "not found."
 | 
  
代码清单 19.3:utf8mac_str.rb
| 1
2
3
4
5
6
 | # encoding: utf-8
str = "ビ"
puts "size: #{str.size}"
p str.each_byte.map{|b| b.to_s(16)}
puts "size: #{str.encode("UTF8-MAC").size}"
p str.encode("UTF8-MAC").each_byte.map{|b| b.to_s(16)}
 | 
  
第 20 章
无代码清单。
第 21 章
代码清单 21.1:power_of.rb
| 1
2
3
4
5
6
7
8
 | def power_of(n)
  lambda do |x|
    return x ** n
  end
end
cube = power_of(3)
p cube.call(5)  #=> 125
 | 
  
代码清单 21.2:prefix.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
 | def prefix(ary, obj)
  result = []               # 初始化结果数组
  ary.each do |item|        # 逐个检查元素
    result << item          # 将元素追加到结果数组中
    if item == obj          # 如果元素与条件一致
      return result         # 返回结果数组
    end
  end
  return result             # 所有元素检查完毕的时候
end
prefix([1, 2, 3, 4, 5], 3)  #=> [1, 2, 3]
 | 
  
代码清单 21.3:total2.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | def total2(from, to, &block)
  result = 0               # 合计值
  from.upto(to) do |num|   # 处理从from到to的值
    if block               #   如果有块的话
      result +=            #     累加经过块处理的值
           block.call(num)
    else                   #   如果没有块的话
      result += num        #     直接累加
    end
  end
  return result            # 返回方法的结果
end
p total2(1, 10)                   # 从1到10的和 => 55
p total2(1, 10){|num| num ** 2 }  # 从1到10的2次冥的和 => 385
 | 
  
代码清单 21.4:counter_proc.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 | def counter
  c = 0          # 初始化计数器
  Proc.new do    # 每调用1次call方法,计数器加1
    c += 1       # 返回加1后的Proc对象
  end
end
# 创建计数器c1并计数
c1 = counter
p c1.call      #=> 1
p c1.call      #=> 2
p c1.call      #=> 3
# 创建计数器c2并计数
c2 = counter   # 创建计数器c2
p c2.call      #=> 1
p c2.call      #=> 2
# 再次用c1计数
p c1.call      #=> 4
 | 
  
代码清单 21.5:proc_source_location.rb
| 1
2
3
4
5
 | prc0 = Proc.new{ nil }
prc1 = Proc.new{|a| a }
p prc0.source_location
p prc1.source_location
 | 
  
第 22 章
代码清单 22.1:get_cathedral.rb
| 1
2
3
4
5
6
7
8
9
10
11
 | require "open-uri"
require "nkf"
url = "http://cruel.org/freeware/cathedral.html"
filename = "cathedral.html"
File.open(filename, "w") do |f|
  text = open(url).read
  f.write text                  # UTF8环境使用此段代码
  #f.write NKF.nkf("-s", text)  # Shift_JIS环境(日语Windows)使用此段代码
end
 | 
  
代码清单 22.2:cut_cathedral.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 | htmlfile = "cathedral.html"
textfile = "cathedral.txt"
html = File.read(htmlfile)
File.open(textfile, "w") do |f|
  in_header = true
  html.each_line do |line|
    if in_header && /<a name="1">/ !~ line
      next
    else
      in_header = false
    end
    break if /<a name="version">/ =~ line
    f.write line
  end
end
 | 
  
代码清单 22.3:cut_cathedral2.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 | require 'cgi/util'
htmlfile = "cathedral.html"
textfile = "cathedral.txt"
html = File.read(htmlfile)
File.open(textfile, "w") do |f|
  in_header = true
  html.each_line do |line|
    if in_header && /<a name="1">/ !~ line
      next
    else
      in_header = false
    end
    break if /<a name="version">/ =~ line
    line.gsub!(/<[^>]+>/, '')
    esc_line = CGI.unescapeHTML(line)
    f.write esc_line
  end
end
 | 
  
代码清单 22.4:simple_grep.rb
| 1
2
3
4
5
6
7
8
9
10
 | pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
File.open(filename) do |file|
  file.each_line do |line|
    if pattern =~ line
      print line
    end
  end
end
 | 
  
代码清单 22.5:simple_scan.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
count = 0
File.open(filename) do |file|
  file.each_line do |line|
    if pattern =~ line
      line.scan(pattern) do |s|
        count += 1
      end
      print line
    end
  end
end
puts "count: #{count}"
 | 
  
代码清单 22.6:simple_count.rb
| 1
2
3
4
5
6
7
8
 | pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
count = 0
File.read(filename).scan(pattern) do |s|
  count += 1
end
puts "count: #{count}"
 | 
  
代码清单 22.7:simple_match.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
count = 0
File.open(filename) do |file|
  file.each_line do |line|
    if pattern =~ line
      line.scan(pattern) do |s|
        count += 1
      end
      print line.gsub(pattern){|str| "<<#{str}>>"}
    end
  end
end
puts "count: #{count}"
 | 
  
代码清单 22.8:simple_match2.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
 | pattern = Regexp.new("(.{10})("+ARGV[0]+")(.{10})")
filename = ARGV[1]
count = 0
File.open(filename) do |file|
  file.each_line do |line|
    line.scan(pattern) do |s|
      puts "#{s[0]}<<#{s[1]}>>#{s[2]}"
      count += 1
    end
  end
end
puts "count: #{count}"
 | 
  
代码清单 22.9:simple_match3.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 | pattern = Regexp.new("(.{0,10})("+ARGV[0]+")(.{0,10})")
filename = ARGV[1]
count = 0
File.open(filename) do |file|
  file.each_line do |line|
    line.scan(pattern) do |s|
      prefix_len = 0
      s[0].each_char do |ch|
        if ch.ord < 128
          prefix_len += 1
        else
          prefix_len += 2
        end
      end
      space_len = 20 - prefix_len
      puts "#{" "*space_len}#{s[0]}<<#{s[1]}>>#{s[2]}"
      count += 1
    end
  end
end
puts "count: #{count}"
 | 
  
代码清单 22.10:simple_match4.rb
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 | len = ARGV[2].to_i
pattern = Regexp.new("(.{0,#{len}})("+ARGV[0]+")(.{0,#{len}})")
filename = ARGV[1]
count = 0
File.open(filename) do |file|
  file.each_line do |line|
    line.scan(pattern) do |s|
      prefix_len = 0
      s[0].each_char do |ch|
        if ch.ord < 128
          prefix_len += 1
        else
          prefix_len += 2
        end
      end
      space_len = len * 2 - prefix_len
      puts "#{" " * space_len}#{s[0]}<<#{s[1]}>>#{s[2]}"
      count += 1
    end
  end
end
puts "count: #{count}"
 | 
  
第 23 章
代码清单 23.1:split_zip.rb
| 1
2
3
4
5
6
7
8
9
10
11
 | code = ARGV[0]
start_time = Time.now    # 获取处理开始的时间
File.open("KEN_ALL.CSV","r:shift_jis").each_line do |line|
  line.chomp!
  rows = line.split(/,/)
  zipcode = rows[2].gsub(/"/,'')
  if zipcode == code
    puts line.encode('utf-8')
  end
end
p Time.now - start_time  # 输出与处理结束时间的差
 | 
  
代码清单 23.2:jzipcode.rb
| 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
 | require 'sqlite3'
class JZipCode
  COL_ZIP = 2
  COL_PREF = 6
  COL_CITY = 7
  COL_ADDR = 8
  def initialize(dbfile)
    @dbfile = dbfile
  end
  def make_db(zipfile)
    return if File.exists?(@dbfile)
    SQLite3::Database.open(@dbfile) do |db|
      db.execute <<-SQL
        CREATE TABLE IF NOT EXISTS zips
          (code TEXT, pref TEXT, city TEXT, addr TEXT, alladdr TEXT)
      SQL
      File.open(zipfile, 'r:shift_jis') do |zip|
        db.execute "BEGIN TRANSACTION"
        zip.each_line do |line|
          columns = line.split(/,/).map{|col| col.delete('"')}
          code = columns[COL_ZIP]
          pref = columns[COL_PREF]
          city = columns[COL_CITY]
          addr = columns[COL_ADDR]
          all_addr = pref+city+addr
          db.execute "INSERT INTO zips VALUES (?,?,?,?,?)",
            [code, pref, city, addr, all_addr]
        end
        db.execute "COMMIT TRANSACTION"
      end
    end
  end
  def find_by_code(code)
    str = ""
    SQLite3::Database.open(@dbfile) do |db|
      db.execute("SELECT * FROM zips WHERE code = ?",
                 code) do |row|
        str += row[1..3].join('')
      end
    end
    str
  end
  def find_by_address(addr)
    str = ""
    SQLite3::Database.open(@dbfile) do |db|
      db.execute("SELECT * FROM zips WHERE alladdr LIKE ?", "%#{addr}%") do |row|
        str += row[0]+' '+row[1..3].join('')+"\n"
      end
    end
    str
  end
end
if __FILE__ == $0
  jzipcode = JZipCode.new("zip.db")
  jzipcode.make_db("KEN_ALL.CSV")
  puts jzipcode.find_by_code("1060031")
  puts jzipcode.find_by_address("東京都渋谷区神宮前")
end
 |