上文讲到,要生成LinkMap,就要修改Build Setting里面的一些Flag,如果需要用脚本来控制,则需要修改到.xcodeproj文件。
今早研究了一早的Python语法,发现都没有很好的办法去修改这个Flag,恰好看到别的文章有思路说,用Ruby来修改,试了一下,果不其然成功了,一不做二不休,干脆把Ruby的简单语法也了解一下吧!
教程来自ruby基础教程(中文第四版)
一. Hello World
print("Hello World!\n")
二. 数组+循环
1. each方法
names = ["a", "b", "c"]
puts names[0]
names.each do |n|
puts n
end
/***
输出
a
a
b
c
***/
数组就很常见了,下面着重讲一下循环:
在Ruby语法中,array.each do |element| end
,代表着枚举一个array的元素element,循环起于do而终于end。
2. times方法
5.times do |n|
puts n
end
/***
输出
0
1
2
3
4
***/
3. for方法
sum = 0
for i in 1..5
sum = sum + i
puts sum
end
/***
输出
1
3
6
10
15
***/
4. while方法
sum = 0
i = 1
while i <= 5
sum = sum + i
i += 1
puts sum
end
/***
输出
1
3
6
10
15
***/
5. break, next
array = ["a", "b", "c", "d", "e"]
array.each do |element|
break if element == "c"
puts element
end
/***
输出
a
b
***/
array = ["a", "b", "c", "d", "e"]
array.each do |element|
next if element == "c"
puts element
end
/***
输出
a
b
d
e
***/
三. 参数
命令ruby file.rb arg1 arg2....
中,可以通过ARGV
来读取到该命令的参数,默认读取到的为字符,也可以将其转化为数字,从而进行运算操作。
str0 = ARGV[0]
str1 = ARGV[1]
puts "#{str0} + #{str1} = #{str0 + str1}"
/***
输出
1 + 2 = 12
***/
num0 = ARGV[0].to_i
num1 = ARGV[1].to_i
puts "#{num0} + #{num1} = #{num0 + num1}"
/***
输出
1 + 2 = 3
***/
四. 文件IO
1. 读取整个文件
filename = ARGV[0]
file = File.open(filename)
text = file.read
print text + "\n"
file.close
2. 逐行读取
如果只需要读取一个大文件里面的前几行,逐行读取会比较节省性能
filename = ARGV[0]
file = File.open(filename)
file.each_line do |line|
print line
end
print "\n"
file.close
3. 带正则表达式的读取
如果需要匹配一个文件里面的一些字符,则可以带上正则表达式
pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
file = File.open(filename)
file.each_line do |line|
print line if pattern =~ line
end
print "\n"
file.close
下面这行命令,代表过滤含tbd字符串的文件,并打印出来
ruby LearnRuby.rb tbd BaseLinkMapResult.txt
五. 引用库
通过require
方法来引用库。
// LearnRuby.rb
def hello
puts "Hello World"
end
// PrintRuby.rb
require './LearnRuby.rb'
hello()
// command
ruby PrintRuby.rb
六. 方法、变量
1. 方法
def hello
puts "Hello World"
end
hello()
2. 变量
局部变量:x,全局变量:$x
// LearnRuby.rb
$x = 1
x = 1
// PrintRuby.rb
$x = 0
x = 0
require './LearnRuby.rb'
puts $x
puts x
// result
1
0
3. 常量
常量用全大写字母声明,与变量相似,但是修改常量会报警告。
TEST = 1
TEST = 2
puts TEST
// result
PrintRuby.rb:2: warning: already initialized constant TEST
PrintRuby.rb:1: warning: previous definition of TEST was here
2
4. 多重赋值
支持对应赋值语法
a, b, c = 1, 2
p [a, b, c]
// result
[1, 2, nil]
利用这个可以做出置换变量
a, b = 1, 2
a, b = b, a
p [a, b]
// result
[2,1]
七. 类
1. 定义
class Person
attr_accessor :name
def initialize(myname = "Default")
@name = myname
end
def greet
puts "Nice to meet u, #{self.name}"
end
end
person = Person.new("Hoben")
person.greet()
// result
Nice to meet u, Hoben
attr_accessor
代表着该类自动生成了getter和setter方法,initialize
是初始化方法,里面可以放置参数,调用的时候,是object = Class.new()
如果需要自定义getter和setter方法,则需要这样来定义:
class Person
# attr_accessor :name
def name # getter
puts "It's Getter"
@name
end
def name=(value) # setter
puts "It's Setter"
@name = value
end
def initialize(myname = "Default")
@name = myname
end
def greet(value)
puts "Nice to meet u, #{value}"
end
end
person = Person.new()
person.name = "NewName"
person.greet(person.name)
// result
It's Setter
It's Getter
Nice to meet u, NewName
注意:在自身类中self.name会调用getter,而@name则不会调用getter方法。(这个和OC很像)
2. public/private/protected
class Person
def PublicMethod
puts "Public"
end
public:PublicMethod
def PrivateMethod
puts "Private"
end
private:PrivateMethod
end
person = Person.new()
person.PublicMethod()
// 这里会报错
person.PrivateMethod()
其实和C++差不多,不多说了
3. 继承与扩展
继承用Son < Father来表示,用super来表示继承父类方法。
class Father
def PublicMethod
puts "Public"
end
public:PublicMethod
def PrivateMethod
puts "Private"
end
private:PrivateMethod
def ProtectedMethod
puts "Father Protected"
end
protected:ProtectedMethod
end
class Son < Father
def ProtectedMethod
super()
puts "Son Protected"
end
public:ProtectedMethod
end
son = Son.new()
son.ProtectedMethod()
// result
Father Protected
Son Protected
当然,也可以在原类的基础上去添加方法,使用扩展。
class String
def expandMethod
puts "It's Expand Method"
end
end
s = String.new()
s.expandMethod()
4. 模块
模块Module和类Class相似,但又有点不同,是Ruby里面特有的用法,不同之处在于:
-
模块不能拥有实例
-
模块不能被继承
通过命名模块,我们可以在引用时省略模块名,直接一个include搞定,如:
// 下面两个一样
p Math::PI
include Math
p PI
如果有两个类,他们有共同的方法,但是又不希望将它们归为同一个Class的话,可以考虑采用模块:
module Common
def commonMethod
puts "Common"
end
Version = "1.0"
end
class SubClass1
include Common
def firstMethod
puts "First"
end
end
class SubClass2
include Common
def secondMethod
puts "Second"
end
end
first = SubClass1.new
second = SubClass2.new
first.commonMethod
first.firstMethod
second.commonMethod
second.secondMethod
include Common
puts Version
// result
Common
First
Common
Second
1.0
Extend方法可以使得单例类包含模块,并把模块的功能扩展到对象中。
module Edition
def edition(n)
"#{self} No.#{n}"
end
end
str = "This is module:"
str.extend(Edition)
p str.edition(4)
// result
"This is module: No.4"
在上面的例子中,可以看到str扩展了一个Edition的module,在edition方法中,他提前设定了"xxx No.x"的字符串,当str扩展了这个module后,就可以先把自身打印出去,再套入输入的结果。
八. 逻辑运算
1. 比较有特色的逻辑
和C++的逻辑运算大同小异,讲一些比较有特色的:
// 当var不为空name = var,当var为空name = Ruby
name = var || "Ruby"
// 当ary为空item为nil,当ary不为空,item为ary[0]
item = ary && ary[0]
// [1, 10]
1..10
// [1, 10)
1...10
2. 重载
二元运算符:可以将运算符名作为方法名,从而重定义运算符。
class Point
attr_accessor :x, :y
def initialize(x=0, y=0)
@x, @y = x, y
end
def position
"(#{x}, #{y})"
end
def +(other) #加法运算
self.class.new(x + other.x, y + other.y)
end
def -(other)
self.class.new(x - other.x, y - other.y)
end
end
p1 = Point.new(1, 1)
p2 = Point.new(2, 2)
p (p1 - p2).position
p (p1 + p2).position
// result
"(-1, -1)"
"(3, 3)"
当然,一元运算符也可以重载
class Point
attr_accessor :x, :y
def initialize(x=0, y=0)
@x, @y = x, y
end
def position
"(#{x}, #{y})"
end
def +@
dup #返回自己的副本
end
def -@
self.class.new(-x, -y)
end
def ~@
self.class.new(y, x)
end
end
p1 = Point.new(1, 2)
p (+p1).position
p (-p1).position
p (~p1).position
// result
"(1, 2)"
"(-1, -2)"
"(2, 1)"
甚至下标也可以重载
class Point
attr_accessor :x, :y
def initialize(x=0, y=0)
@x, @y = x, y
end
def position
"(#{x}, #{y})"
end
def [](index)
return x if index == 0
return y if index == 1
return "Out of Range"
end
def []=(index, value)
self.x = value if index == 0
self.y = value if index == 1
return "Out of Range"
end
end
p1 = Point.new(1, 2)
p1[0] = 3
p1[1] = 4
p2 = Point.new(p1[0], p1[1])
p p2.position
// result
"(1, 2)"
九. 异常处理
begin ~ rescue ~ ensure ~ end来描述,需要抛出异常时,则调用raise方法,
类似于 try ~ catch ~ finally,调用throw抛出异常
begin
有可能发生异常的处理
raise...
rescue => 变量
发生异常后的处理
ensure
不管是否发生异常都希望执行的处理
end
运用到打开文件中,如果打开异常也需要关闭文件,则可以用该方法来处理。
file = File.open("sample.txt")
begin
file.each do |file|
file.each_line do |line|
puts line
end
end
rescue Exception => e
puts e.exception
ensure
file.close
end
十. 块
块,即代码块,会在循环、替换算法中用到,也可以作为参数传入另一个块里面,和iOS的block有异曲同工之妙。
1. 替换算法
Array提供sort方法,用于从小到大去排序数组,但是如果我们要写cmp的话,就要自己去定义了。
array = ["d", "cc", "bbb", "aaaa"]
sorted = array.sort
sortedByLength = array.sort { |a, b| a.length <=> b.length}
p sorted, sortedByLength
// result
["aaaa", "bbb", "cc", "d"]
["d", "cc", "bbb", "aaaa"]
根据上面的例子,可以看到,sort函数是根据字母的大小来判断的,而加入了cmp,则可以根据数组长度来判断。
其中,<=>表示

2. 传递块
def total(from, to)
result = 0
from.upto(to) do |num|
if block_given?
result += yield(num)
else
result += num
end
end
return result
end
p total(1, 5)
p total(1, 5){|num| num ** 2}
// result
15
55
yield
代表取块里面的值,block_given
可以用于判断是否有传入块,from.upto(to)
代表遍历from..to
,也可以用(from..to).each
来代替,可以看到,当传入块的时候,计算的结果为。
yield
可以接收若干个参数,并使用这些参数。
def block_test
yield() # 0个块变量
yield(1) # 1个块变量
yield(1, 2, 3) # 2个块变量
end
p '通过|a|接收变量'
block_test do |a|
p [a]
end
p '通过|a, b, c|接收变量'
block_test do |a, b, c|
p [a, b, c]
end
// result
"通过|a|接收变量"
[nil]
[1]
[1]
"通过|a, b, c|接收变量"
[nil, nil, nil]
[1, nil, nil]
[1, 2, 3]
网友评论