Ruby Quick Start (1) -- A Glimpse of Syntax

学习Ruby时在网上找到了一本小册子《Ruby语言入门教程v1.0》,虽然是07年的东西了,但是作为快速熟悉Ruby基本语法还是很有帮助的,做一下笔记。

开始前先问下自己两个问题。

(1) 我为什么要学习Ruby?

为了Web开发。

(2) 为什么选择Ruby,而不是Python,PHP?

看了知乎上的这个答案

  • 假如你想帮他尽快找个活儿, 赚到钱, 推荐 PHP
  • 假如你想让他成为一个高效工程师, 推荐 Python
  • 假如你想让他爱上他的工作, 推荐 Ruby

无论如何,别人的答案只能作为参考,自己尝试过后才有资格评价,所以最好的方法就是亲自动手学习下Ruby。





第一章 概述

松本行弘(Matz)是日本一家开源软件公司的程序员,在工作中,他希望有一种比 Perl 强大,比 Python 更面向对象的语言。从1993年2月,他开始设计一个全新的自己的语言,1994年12月发布了第一个 alpha 版本,并且将这种新语言定名为Ruby(红宝石)。

Ruby比Python年轻。



第三章 语法快览

注释与分行

单行注释用 #

多行注释用

1
2
3
=begin
这里是注释,=begin和=end前面不能有空格
=end

分号 ; 表示一个语句的结束;



标识名

Ruby的标识名区分大小写

Ruby使用一个约定来帮助它区别一个名字的用法:名字前面的第一个字符表明这个名字的用法

  1. 局部变量方法参数方法名称应该用一个小写字母开头或者用一个下划线_开头;
  2. 全局变量用美元符作为前缀 $
  3. 实例变量@ 开头;
  4. 类变量@@ 开头;
  5. 类名模块名常量应该用大写字母开头。



类库

Ruby 像 C++ 一样,有许多类库可以供你使用,其中的 I/O 库很完善。如print, puts等可以直接使用。

I/O 是 输入/输出,这是 Ruby 语言 Kernel 模块的方法,Mix-in 在根类 Object 中的。

puts 把它的所有参数写出来,每一个参数结束都加入一个换行符print 也写出它的参数,不过没有换行。你可以指明输出到一个文件,不说明,则一般输出到显示器。

还有一个常用的输出方法是 printf,它按格式输出参数。

1
printf "Number: %4.3f, String: %s", 7.8, "hi!"

printfprint 一样,不主动换行,换行可以用“\n”。

1
2
printf "Number: %4.3f, String: %s\n", 7.8, "hi!"
print "hello\n"

介绍了三个输出方法,再介绍一个输入方法:gets ,它从你的程序的标准输入流中返回一行。一般用来从键盘或文件读入一行数据。

1
2
str = gets
puts "You input #{str}"



数据类型

Ruby 数据类型有数字,字符串,数组,哈希表,区间,正则表达式。

(1) 字符串是在''(单引号) 、 ""(双引号)之间的代码。

(2) 数组的下标从0开始。Ruby的数组和其它语言不同,数组的每个元素可以是不同的类型:

1
[ 2.4, 99, "thank you", [ a, b ,c ], 78 ]

(3) 区间:
1..5 表示1, 2, 3, 4, 5 (闭区间)
1...5表示1, 2, 3, 4 (左闭右开)

(4) hash表,看下面的snippets:

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
new_hash1 = {} # 创建空hash表
new_hash1[:key_a] = 'contents1' # 使用Symbol作为key,Symbol通过前面加冒号:定义
new_hash1[:key_b] = 'contents2'
puts new_hash1[:key_a]
puts new_hash1 # 打印整个hash表
new_hash2 = {:key_a=>'contents1', :key_b=>'contents2'} # hash表赋值
puts new_hash2[:key_b]
my_hash={}
my_hash["key_a"]=123456 # 使用string作为key
puts my_hash["key_a"]
puts my_hash
# hash表的一些方法
person = {:name => "lxee", :age => 25, :sex => "male"}
p person.keys
p person.values
puts person.include?(:sex) # 判断是否包含key为:sex的元素
puts person.include?("sex") # 判断是否包含key为"sex"的元素
person.delete(:sex) # 删除key为:sex的元素
puts person.has_key?(:sex) # 判断是否包含key为:sex的元素
puts person.length.to_s # 输出Hash对象长度
# 上面hash表的遍历
person.each do |key, value| # each迭代器迭代输出Hash对象里全部元素
puts key.to_s+" : "+value.to_s
end
person.each_pair do |key, value| # each_pair迭代器迭代输出Hash对象里所有key-value对
puts key.to_s+" : "+value.to_s
end
person.each_key do |key| # each_key迭代器迭代输出Hash对象里所有key
puts key.to_s
end
person.each_value do |value| # each_value迭代器迭代输出Hash对象里所有value
puts value.to_s
end

注意上面关于hash表的代码片我们分别使用了symbolstring来作为hash表的key

在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字。创建一个 Symbol 对象的方法是在名字或者字符串前面加上冒号:

在 Ruby 中字符串也是一种对象,即 String 对象。无论其结构还是操作和 Symbol 对象都是不同的。

在 Ruby 中每一个对象都有唯一的对象标识符(Object Identifier),可以通过 object_id 方法来得到一个对象的标识符。

每个 String 对象都是不同的,即便他们包含了相同的字符串内容;而对于 Symbol 对象,一个名字(字符串内容)唯一确定一个 Symbol 对象。

值得注意的是创建 Symbol 对象的字符串中不能含有’\0‘字符,而 String 对象是可以的。



赋值与条件运算符

Ruby赋值

1
2
3
4
5
6
a = 1; b = 2 + 3 # a = 1, b = 5
a, b = b, a # a = 5, b = 1
a = b = 1 + 2 + 3 # a = 6, b = 6
a = (b = 1 + 2) + 3 # a = 6, b = 3
x = 0 # x = 0
a, b, c = x, (x+1), (x+2) # a = 0, b = 1, c = 2

Ruby条件运算符

<, <=, >, >=:比较两个对象的值的大小

==, !=:比较两个对象的值是否相等

1
a = 1; b = 1.0; a == b # true

eql?:比较两个对象的值、类型是否相等

1
a = 1; b = 1.0; a.eql?(b) # flase (a为整数型,b为浮点型)

equal?:比较两个对象在内存中地址是否相同

1
2
a = 1.0; b = 1.0; a.equal?(b) # false
a = 1.0; b = a; a.equal?(b) # true, 注意这里可以看出"b = a"是传引用而不是传值

<=>:比较两个对象的大小,大于、等于、小于 分别返回1, 0, -1

1
2
"aab" <=> "acb" # -1 (第二个 a 的 ASCII 码小于 c)
[5] <=> [4,9] # 1 (第一个元素 5 > 4)

===:右边的对象是否在左边区间之内,返回 true, flase

1
2
puts (0..9) === 3.14 # true
puts ('a'..'f') === 'c' # true

=~ (匹配):用来比较是否符合一个正则表达式,返回模式在字符串中被匹配到的位置,否则返回 nil(Ruby中nil和false为假,它们的区别有待研究)

!~ (不匹配):断言不符合一个正则表达式,返回 true, false


Ruby条件判断语句

(1) 单行 if 语句

有两种方式:

  1. if 条件1 then 语句1; 语句2; ... 语句n end
  2. (语句1; 语句2; ... 语句n) if 条件

(2) 多行 if 语句

1
2
3
4
5
6
7
if 条件
语句1; 语句2; ... 语句n
elsif 条件
语句1; 语句2; ... 语句n
else
语句1; 语句2; ... 语句n
end

(3) unless(除非)条件语句:

unless 条件 = if not (条件)

(4) case分支条件语句

1
2
3
4
5
6
7
8
9
10
11
case 对象
when 可能性1
语句1; 语句2; ... 语句n
when 可能性2
语句1; 语句2; ... 语句n
...
when 可能性n
语句1; 语句2; ... 语句n
else
语句1; 语句2; ... 语句n
end



条件判断与循环

Ruby循环语句

(1) while 循环

1
2
3
while 条件
语句1; 语句2; ... 语句n
end

(2) 单行 while 循环

1
(语句1; 语句2; ... 语句n) while 条件

(3) until 循环

1
until (条件) = while not (条件)

(4 )for ... in ... 循环

1
2
3
for 变量 in 对象
语句1; 语句2; ... 语句n
end

对象可以是数组,区间,集合等

(5) break, next, redo, retry

在循环体内,如果遇到:
break 跳出当层循环;
next 忽略本次循环的剩余部分,开始下一次的循环;
redo 重新开始循环,还是从这一次开始;
retry 重头开始这个循环体。

(6) times, upto, downto, each, step

1
2
3
4
5
3.times { print "Hi!" } # Hi!Hi!Hi!
1.upto(9) {|i| print i if i<7 } # 123456
9.downto(1){|i| print i if i<7 } # 654321
(1..9).each {|i| print i if i<7} # 123456
0.step(11,3) {|i| print i } # 0369

注意step第一个参数是limit,第二个参数是步长