Ruby语法速查


###Ruby 2.0 简明语法整理

##目录

变量/常量

  • 全局变量$标识

def basic_method
  puts $x
end

$x = 10
basic_method()

  • 全局常量大写开头

CONST_V = "abc"

类型

  • 整型,浮点型,字符串
a = 10;
print a.to_f #10.0

a = 3.3
print a.to_i

a = 100
print a.to_s

  • 浮点型

d = 7.3-7.2
puts d 
=> 0.09999999999999964

require "bigdecimal"

a = BigDecimal.new("7.3")
b = BigDecimal.new("7.2")
puts a-b 

=> 0.1E0

表达式

  • !

a,b = 10,20
c = 0
if a==b
  c = 1

elsif a != b
  c = -1 
end

  • eql? :检测类型和值

c = 10
r = a.eql?(c)
puts r #true
d = 10.0
r = a.eql?(d)
puts r #false


  • <=>:
x<=>y

x>y 则返回1 , x<y则返回-1 , x=y则返回0

字符串

  • 拼接:

 #使用+号
x = "a"
y = "b"
z = x+y

 #使用<<号
c = "a"<<" "<<"b"

  • inspect:查看字符串

string = "  Hello world"
d = string.inspect
puts d
=> "\"  Hello world\""

  • chop:砍掉末尾字符

string = "  Hello world"
e = string.chop
puts e
=> "  Hello worl"

  • include? :包含substring

b = string.include?("Hello")
puts b

  • 转义符号:

\n, \t:tab , \b : 删除 , \v 换行+tab


 ##字符串中的引号,双引号可被#{}解析
puts "Hello \" world \" " 
=> Hello " world " 

 ##使用单引号,不会被#{}解析
puts 'Hello "world"'
=> Hello "world" 

 ##字符串中的\
puts "Hello \\ world"
=>Hello \ world

  • 使用标记来约定字符串的开始和结束:«ID xxxxx ID

x = <<JAYSON_
this is some
thing
else,haha
JAYSON_

puts x

  • 重复字符串

x = "b"*5
puts x

  • 格式化:#{}

x = 10
y = 20
puts "#{x} + #{y} = #{x+y}"

  • 格式化:使用sprintf

r = rand(100) #0-100内的随机数
str = sprintf("%.1f",r)
puts str.inspect

  • %q{}不会被#{}解析

x = %q{ this is some
thing 
else,haha}

=> " this is some\nthing \nelse,haha"

  • %{} 会被#{}解析

name = %{Jason}

  • %w{}将字符串转换为字符串数组

strlist2 = %w{dog monkey pigg cock} ##将元素转换为字符串数组
puts strlist2.inspect

  • 替换substring
x = "foobar"

 #sub方法只将第一个bar变成boo
y = x.sub('bar','boo')
puts y

x = "foobarxoobar,ioo="

 #gsub方法将所有bar都变成boo
y = x.gsub('bar','boo')
puts y  
 
  • 正则表达式以/xxx/表示

 #将前两个字符替换成Hello
y = x.sub(/^../,'Hello')
puts y

 #将后两个字符替换为Hello
y = x.sub(/..$/,'Hello')
puts y

 #x.each{|i| puts i} #--wrong!
 #需要使用scan
x.scan(/./){|i| puts i} #--Right!

 #scan的参数为正则表达式
x = "this is something I will never do"
x.scan(/\w\w/){|i| puts i}

 #\w的意思是匹配数字,字母下,划线,对每个字符进行匹配 
 # \w\w 是对两个字符进行匹配
x.scan(/\w+/){|i| puts i}

 ###.scan方法实际上返回的时数组
p = x.scan(/\w+/)
puts "-----"
puts p.class  #array
puts "-----"
puts p
puts "-----"
 #\w+ :+的意思是一直向后匹配,直到遇见非数字,字母,下划线

x = "I spent 100 dollars on this machine which is now 200 dollars"
x.scan(/\d+/){|i| puts i}
 #匹配出数字

 #匹配字符集[....]匹配[]中的字符集
x = "this is a test"
x.scan(/[aeiou]/) {|i| puts i}
x.scan(/[a-m]/){|i| puts i}

  • 访问char

x = "abc"
puts x[0]

  • char的index

string.index("a") ##1

  • 字符串匹配

 #(1)根据正则匹配:
 #检测字符串中是否包含某字符: 使用=~
 #检测字符串中不包含某字符: 使用!~
puts "get string" if "jayson loves basketball" =~ /[basketball]/
puts "String contains no digits" unless "jayson loves basketball" =~ /[0-9]/


 #(2)使用match方法
puts "String has matched" if "jayson loves basketball".match("loves")

  • 其它

 #reverse
string = string.reverse()
puts string

 #upercase
string = string.upcase()
puts string

 #lowercase
string = string.downcase()
puts string

 #swap
string = string.swapcase()
puts string

 #length
l = string.length
puts l

 #size == length
s = string.size
puts s

 #split
string = "hello world"
list = string.split(" ")
puts list.inspect

 #concat
string.concat("another string")
puts string

控制流

  • if

 ##单行判断
puts "a>10" if a>10

 #if-elsif-else
if a<10
  puts "a<10"
elsif
  puts "a=10"
else
  puts "a>10"
end

  • unless
unless a>10 
  puts "a>10"
end

  • 三元操作
type = a > 10 ? "1" : "2"
puts type

  • case-when

fruit = "orange"

case fruit
when "orange"
  color = "orange"
when "apple"
  color = "red"
when "banana"
  color = "yellow"
else
  color = "unknown"
end

  • while

x = 10

while(x>=1)
  x = x/2
  puts x
end

 #单行
x=10
x = x/2 while x >= 1 
puts x

  • until


x = 10

until x <= 1
  x = x/2
  puts x
end

 #单行
x = 10
x = x/2 until x<1 
puts x

  • loops

array = [1,2,3,4]
for i in array do
  puts "i is #{i}"
end

strlist1 = ["a","b","c"]
puts strlist1.inspect

strlist2 = %w{dog monkey pigg cock} ##将元素转换为字符串数组
puts strlist2.inspect

for animal in strlist2 do
  next if animal == "monkey" ##continue
  puts "#{animal}"
end


Symbol

symbol是无值常量,全局唯一,Ruby特性


hello = :key
puts "equal" if hello == :key #equal
a = {:key => "hh"}
puts a[:key] ## hh

 #symbol:在内存中只创建一次
treehouse = {'name'=>'Treehouse','location' => 'Treehourse Island'}
 
 #如果再创建一个treehouse,那么所有的key都要重新创建一遍
 #如果使用symbol,key不会重新创建
treehouse = {:name => 'Treehouse', :location => 'Treehouse Island'}

Array

  • 数组个数

a = p.count

  • 清空

a.clear

  • 数组索引

puts x.first
puts x.last

puts x[0]
puts x[-1] ##最后一个

puts x.first(2) ##前两个
puts x.at(0)


  • 数组中每个元素的类型可以不同
x = [1,"2",3.0]
  • 反转

x.reverse()

  • 数组遍历
 #使用do-each
q.each do |i|
  puts i.to_s
end

#使用do-each with index
q.each_with_index do |item, index|
  puts "current_index: #{index}"
end


 #使用block
q.each { |i| 
  puts i.to_s + "x"
}

 #使用collect
[1,2,3,4].collect{|element| element*2}

  • 数组包含某个元素

x = [1,2,3]
puts x.include?("x")
puts x.include?(3)

  • 数组的push操作
x << "wrod"
x.push("word")

x += [1,2]

  • 数组的pop操作
x.pop

  • 数组的join操作:

 #如果一个数组全是字符串,可以使用.join方法,将数组中的元素连接起来

x = ["jj","ss","gg"]
puts x.join()

=> jjssgg

puts x.join(', ')

=> jj, ss, gg

  • 字符串按符号分割:

x = "short sentence; Another; no more"
q = x.split(';')
puts q.class 
=> array

puts q
=> short sentence Another no more

使用inspect方法使输出格式更易读,所有对象都有inspect方法:


x = "short sentence; Another; no more"
p = x.split(';').inspect 

puts p  
=>["short sentence", " Another", " no more"]

  • 数组相加:
p = [1,2,3]
q = ["1",2,"33"]  
z = p+q
print z

=> [1, 2, 3, "1", 2, "33"]

  • 数组相减:

 #两个数组相减
p = [1,2,3]
q = [4,5,6]
z = p-q
print z 

=> 1,2,3

  • slice: 取数组的某些值,组成一个新数组, 参数为index值,不修改原array

list1 = [1,2,3]
ele = list1.slice(1); puts ele.inspect #[2]
slice = list1.slice(1,2) ; puts slice.inspect #[2,3]

  • slice! :取数组的某些值,组成一个新数组, 参数为index值,修改原array

slice = list1.slice!(1,2) ; puts list1.inspect #[1]

  • unshift :在头部插入元素

a = [1,3,4]
a.unshift 2

=>  [2, 1, 3, 4]

  • rindex :返回数组元素的index
	
a = [1,2,3,"a","s"]
a.rindex "a"

=> 3

  • 多维数组

array = [1,2,3]
array = array.push([2,3,4])
puts array.inspect 
=> [1, 2, 3, [2, 3, 4]]

 #展成1维数组
array = array.flatten
=> [1, 2, 3, 2, 3, 4]

  • sort & compare

array = [5,1,3,5,4,9]
array1 = array.sort ; puts array1.inspect()
array1 = array.sort{|a,b| a<=>b} ; puts array1.inspect()
array1 = array.sort{|b,a| a<=>b}.reverse ; puts array1.inspect()
array1 = array.sort{|b,a| a<=>b}.reverse.uniq ; puts array1.inspect() ##uniq去重

  • any? all?

array = [5,1,3,5,4,9]
ret = array.any?{|e| e>3} ; puts ret.inspect()
ret = array.all?{|e| e>3} ; puts ret.inspect()

  • select :选出符合条件的元素
newArray = array.select{ |e| e>3}; puts newArray.inspect()
  • reject :去除符合条件的元素
newArray = array.reject{ |e| e>3}; puts newArray.inspect()
  • map:
newArray = array.map{|e| e*2 }; puts newArray.inspect()

Hash

  • 创建

h = Hash.new() ; puts h.inspect()
h = {"hello" => "world"}
h = Hash.new{|hash,key| hash[key] = "Default value for #{key}"}

  • 清空

h.clear;puts h.empty?

  • 个数

map.size

  • 访问

map['cat'] = 'boss'

  • 遍历

map.each{ |k,v|
	
	puts "#{k} => #{v}"
}


h.each_pair {|k,v| 
	
	puts "the key at #{k} is #{v}"
	
}

h.each_key{|k| 
	puts "the key is #{k}"
	
}

h.each_value{|v| 
	puts "the value is #{v}"

}

h.select{|k,v| k == "501"};puts h.inspect

h.keep_if{|k,v| k == "502"}; puts h.inspect


  • 删除

map.delete('cat')
map.delete(0)
map.delete_if {|key,value| key =="some key"}

  • 所有keys/values

map.keys
map.values

  • key/value存在?

puts h.has_key?("candy")
puts h.has_value?("candy")

  • to array
h = {"501" => "cctv1", "502" => "cctv2", "503" => "cctv3"}
puts h.to_a.inspect

=>[["501", "cctv1"], ["502", "cctv2"], ["503", "cctv3"]]

  • find

h = {"501" => "cctv1", "502" => "cctv2", "503" => "cctv3"}
puts h.find{|k,v| k == "503"}.inspect;  ##["503","cctv3"]返回数组
puts h.find_all{|k,v| v.match("cc")}.inspect 
puts h.all?{|k,v| v.match("cctv1")}
puts h.any?{|k,v| v.match("cctv1")}

  • map
puts h.map{|k,v| v += "ss"}.inspect #将value的值映射为#["cctv1ss","cctv2ss","cctv3ss"]

  • reject
h.reject{|k,v| k == "cctv1"}.inspect

迭代器


 #例如upto:从1到5
1.upto(5) {puts "upto"}

 #downto:从10递减到5
10.downto(5) {puts "downto"}

 #从0开始,到50,每次步进5
0.step(50,5) do
  puts "step"
end

 #如果要打印出循环的index,怎么办?

 #使用block
1.upto(5) {|i| puts i}

 #使用do-end
10.downto(5) do |i|
  puts i
end

Block

  • block:是匿名函数,可以当参数传递,当参数时需要用&符号声明参数是block类型

def say_hello(&block)
  puts "Hello world"
  if block_given?
    block.call
  else
    puts "no block given"
  end
end

say_hello {puts "call from block"}

say_hello do
  puts "call from block"
end

 #block的返回值
def say_name(&block)
  name = block.call
  puts name
end

say_name{"Jayson"}


  • yield

def test_yield(&block)
  for i in 1..5 do
    yield i ##will call block, pass i‘s copy to the block
  end
end

test_yield {|i| puts "#{i*2}"} #2,4,6,8,10

class SimpleBenchmarker

def self.go(times, &block)

puts "----------Benchmarking started------------"
start_time = Time.now
puts "start time : #{start_time}\n\n"
times.times do |t|
  print "."
  block.call
end
print "\n\n"
end_time = Time.now
puts "End Time:\t #{end_time}\n"
puts "----------Benchmarking finished-----------"
puts "Result :\t\t #{end_time - start_time} seconds"

end end

SimpleBenchmarker.go 5 do time = rand(0.1..1.0)
sleep time end

Proc

  • proc :用来创建匿名函数 - block

proc_b = Proc.new {puts "hello b"}
proc_a = proc {puts "hello a"}
proc_b.call
proc_a.call

Lambda

  • lambda: 一种proc

my_lambda_1 = lambda {}
my_lambda_2 = -> lambda {}

proc和lambda的区别是,lambda必须要传入参数


my_proc = proc {|name| puts "hello #{name}"}
my_proc.call ("jayson")

my_lambda = lambda {|name| puts "hello #{name}"}
my_lambda.call ("candy")

def return_from_proc

  p = proc {return "return from proc"}
  p.call
  return "return from function"
  
end

def return_from_lambda

  l = lambda {return "return from lambda"}
  l.call
  return "return from function"
end

puts return_from_proc()
puts return_from_lambda()


Class

  • 成员变量用@定义

class Square
  
  ##默认构造
  def initialize(side_length)
    
    ##定义成员变量用@
    @side_length = side_length
  
  end
  
  def area
  
    priFunc() ##调用private方法
    self.pubFunc() ##调用public方法
    @side_length * @side_length
    
  end
  
private
  def priFunc()
    puts "private func called"
  end

public
  def pubFunc()
    puts "public func called"
  end

end


  • 继承,类方法,类成员

class Test < Object ##继承:默认都是从object继承

  ##定义类成员的getter方法
  def self.clz_counter
    @@clz_counter ##计数器
  end
  
  def initialize
    
    ##类成员
    if defined? (@@clz_counter)
      @@clz_counter += 1
    else
      @@clz_counter = 1
    end
  end
  
  ##类方法
  def self.test_method1
    puts "test self_method1"
  end
  
  def Test.test_method2
    puts "test self_method2"
  end

end

  • override

class ParentClz
  
  #父类的pFunc方法返回a
  def pFunc (a)
     a
  end
  
end

class ChildClz <ParentClz
  
  ##重写p方法,返回ax
  def pFunc (a)
     a.to_s + "x"
  end
  
end

  • 修改或增加现有类的方法

class ChildClz
  
  def pFunc(a)
    a.to_s+"x"+"x"
  end
  
  def qFunc
    puts "this method is added"
  end
  
end


  • attr

class AttrClz
  
  ##自动支持.预发的getter和setter
  attr_accessor :name, :age
  
  ##私有方法
  private
  def private_method
  end
  
  ##共有方法
  public
  def public_method
  end
  
  def age
    @age
  end
  
  ##protect方法
  protected :age
  
end

  • 内部类

class InsideClz
  
  def InsideClz.giveMeDrawingClz
    Drawing.new
  end
  
  ##内部类
  class Drawing
    def print
      puts "this is a print method inside Drawing"
    end
  end
  
end

a = InsideClz.new
InsideClz.giveMeDrawingClz.print

 ##返回Drawing 对象
a = InsideClz::Drawing.new
a.print


命名空间


module NameSpace1

  def NameSpace1.random
    rand(100)
  end

end

module NameSpace2
  
  def NameSpace2.random
    rand (10)
  end
end

puts NameSpace1.random
puts NameSpace2.random

Module


module ToolBox
  
  class Ruler
    attr_accessor :length
  end
end

module Country
    
  class Ruler
    attr_accessor :name
  end
end

a = ToolBox::Ruler.new
a.length = 50

b = Country::Ruler.new
b.name = "kate"

puts a,b

include

在某个作用域中引入其它namespace中的方法或者类

module UsefulFeatures
  
  def class_name
    
    self.class.to_s
    
  end
  
end


class SomeClass
  
  ##包含了其它类
  include UsefulFeatures
  
end

x = SomeClass.new
puts x.class_name


系统对array默认include的两个类: Enumerable

  • each方法:

[1,2,3].each{|i| puts i}

除了each方法外,还提供了20多个有用的放法: collect,detect,find,find_all,include?,max,min,select,sort,to_a

list = %w{this is the longest word check}
puts list.inspect

  • collect
[1,2,3].collect{|i| puts i.to_s+"x"}
  • detect
a = [1,2,3].detect{|i| i.between?(2,3)}
puts a #2
  • select
a = [1,2,3,4,5].select{|i| i.between?(2,3)}
puts a

  • sort
[4,3,2,1].sort #[1,2,3,4]
  • min/max
[1,2,3].max 
[1,2,3].min

异常

  • begin-rescue

begin 
  puts 10/0
rescue
  puts "crash"
end

  • catch-throw

catch(:finish) do
  1000.times do
    x = rand(1000)
    throw  :finish if x == 123
  end
  
  puts "the random number is 123"
end

  • rescue-ensure

 #ensure : 类似finally,保证会执行
 #rescue : 

def header(&block)
  puts "this is our header"
  block.call
  puts "this is our footer"
  
rescue
  puts "this is where rescue an error"  
ensure
  puts "this one is ensure to be called"
end

header {puts "this block will crash"; raise "this is an error"}

文件操作

  • 创建文件

 ##如果用new打开文件,需要调用close
a = File.new("./input.json","r")
puts a.class ## File

 ##默认以换行符进行分割
a.each{|line| puts line}
a.close


a = File.new("./input.json","r")
 ##如果用其他符号分割:
a.each(':'){|line| puts line}
a.close


a = File.new("./input.json","r")
 ##逐个字节读取I/O流
a.each_byte{|byte| puts byte}
a.close

a = File.new("./input.json","r")
puts a.readlines.join("--")
a.close

  • 读文件

 ##更简单的读文件的方法,a为字符串
a = File.read("./input.json")
puts a.class ##string, not File
puts a

 ##文件指针
f = File.open("./input.json")
f.pos = 8 ##从第8个字节后开始读取
puts f.gets
puts f.pos


  • 写文件

 ##创建文件,“w”为只写,创建新文件
File.open("text.txt","w") do |f|
  f.puts "This is a test\nthis is another test"
end

 ##创建文件,可以持续写入"a",用来输出日志
f = File.open("logFile.txt","a")
f.puts Time.now
f.close

 ##创建文件,可读写"r+"
f = File.open("text.txt","r+")
f.write "12345"
f.close

f = File.open("text.txt","r")
puts f.gets ##输出一行
f.close

  • 删除

File.delete("file1.txt")

  • 重命名

File.rename("text.txt","test.txt")

  • 文件是否存在

b = File.exist?("file1.txt")

  • 文件是否相同

b = File.identical?("file1.txt","file2.txt")

  • 文件是否读取到末尾

f = File.open("test.txt","r")
f.each{ |line| puts line}
puts "end of file" if f.eof?
f.close

  • 文件夹路径

puts Dir.exist?
puts Dir.pwd

  • 改变当前目录

Dir.chdir("~/ruby/")
Dir.chdir("~/rails/")

  • 列出当前路径下的所有文件

puts Dir.entries("~/ruby/").join("\n")

  • FileUtil

require 'fileutils'
here = File.dirname(__FILE__) #__FILE__:built-in ruby value : 表示当前文件所在目录
puts here
puts File.expand_path(here)

puts Dir.entries(here) #列出here目录下所有文件和文件夹

 #fileutil创建目录
FileUtils.mkdir_p(here+'/stuff')
puts Dir.entries(here)

 #创建文件
FileUtils.touch('file1')
puts Dir.entries(here)

ENV


puts RUBY_PLATFORM ##universal.x86_64-darwin13

ENV.each{ |e| puts e.join(': ')}

puts ARGV.join('-')

Kernel

kernel:ruby的kernel是一个公共库,里面定义了一些全局API

puts "hello world"

等同于:

Kernel.puts "Hello world"

Object

Object:所有全局函数都是Object对象的methods

全局函数:

def func(a)
  puts a
end

调用全局函数:

func(10)

等同于:

Object.func(10)

Date



 #date
require 'date'
require 'time'

 #格式化时间:
date = Date.new(2014,4,1)
puts date.to_s
puts date.strftime("%m/%d/%Y")
puts date.strftime("%b/%d/%Y")
puts date.mday
puts date.day
puts date.year
 
 #date 可以解析
date2 = Date.parse("2014/4/3")
puts date2-date #2/1
puts (date2-date).to_i

 #time
time = Time.new
puts time

YAML


require 'yaml'
array = %w(dog cat frog)
puts array.to_yaml
hash = {:name => "jayson", :location =>"TB"}
puts hash[:name]
puts hash.to_yaml

 #yaml用于写配置文件
File.open('./config.yml','w+') {|f|
  
  f.puts hash.to_yaml
  
}

config = YAML.load(File.read('./config.yml'))
puts config.inspect

class Frog
  attr_accessor :name
end

frog = Frog.new
frog.name = "jayson"
yaml = frog.to_yaml
puts yaml.inspect

same_frog = YAML::load(yaml)
puts same_frog.inspect


ERB


require 'erb'

hash = {:name => "jayson", :location =>"TB"}

 #以TEMPLATE开始到TEMPLATE结束之间的这段字符串会被复制到template这个变量中
 #ruby代码需要包含在<%= ... %>中执行
 
template = <<-TEMPLATE

From the desk of <%= hash[:name] %>
-----------------------------------
Welcome to <%= treehouse[:location] %>.

we hope you enjoy stay.
-----------------------------------

<% hash.keys.each{|k| %>
  key:<%= k %>
<% } %>

TEMPLATE

erb = ERB.new(template)
puts erb.result