Ruby学习笔记(4) - 基本的类型

  • 整形是可以任意长度的,只要内存足够,没有任何限制。这一点并不像C++和JAVA那样。在输入的时候,数字之间的下划线(_)是会被忽略的。
123_456     >>>  123456    # 下划线被忽略了
  • 如果整形数的范围在int和long里面的话,那么他的类型是Fixnum;如果超出这个范围,类型就是Bignum。(在Ruby里面,一切都是类,包括所谓的基本类型)
  • 在字母或者一些控制字符前面加问号(?),就是取该字符编码对应的数值。
?a                        # character code
?/n # code for a newline (0x0a)
?/C-a # control a = ?A & 0x9f = 0x01
?/M-a # meta sets bit 7
?/M-/C-a # meta and control a
?/C-? # delete character
  • 浮点数的类型是Float,对应着相应的体系的double类型。
  • String是只是一串8-bit的byte,其中可以包含2进制byte,不过要使用/(backslash)来引用。
  • String literal的几种:
# 单引号://表示一个/,/‘表示一个单引号'。
'escape using "//"' » escape using "/"
'That/'s right' » That's right

# 双引号:支持类似于shell的变量替换,使用#{expr}的格式。
"Seconds/day: #{24*60*60}" » Seconds/day: 86400
"#{'Ho! '*3}Merry Christmas" » Ho! Ho! Ho! Merry Christmas
"This is line #$." » This is line 3

# %q和%Q:当后面跟的是{[(<的话,在对应的closed的符号之间的字符都是string的内容;否则就是下一个相同字符的之间的内容。
# 注意%q相当于单引,而%Q相当于双引。
%q/general single-quoted string/ » general single-quoted string
%Q!general double-quoted string! » general double-quoted string
%Q{Seconds/day: #{24*60*60}} » Seconds/day: 86400

# here documents: 这个和shell的用法是一样的。
aString = <<END_OF_STRING
The body of the string
is the input lines up to
one ending with the same
text that followed the '<<'
END_OF_STRING
  • String的split方法用来根据regex将line中的域分开,并可以将结果分别赋值。用法如下:
songFile.each do |line|
file, length, name, title = line.chomp.split(//s*/|/s*/) # 这里的chomp方法是用来将每行的末尾的newline字符去掉。注意分别赋值的用法。
songs.append Song.new(title, name, length)
end
  • String的scan方法是用regex来匹配line中的域,匹配的域会被分别返回。结果可以用来分别赋值。
  mins, secs = length.scan(//d+/) # 这里的分别赋值
  • Range也是Ruby里面的基本类型,可以用来表示排列(包括数字,字符串和对象),条件表达式,区间。其中如果要用来表示对象的排列的话,那么这个对 象一定要实现succ方法,这个方法返回这个对象的对应的下一个对象。同时还要实现<=>运算符运算,这个运算表示一般的条件比较,在小于、 等于、大于的情况下分别返回-1、0、1。
# 基本的用法,两点表示包含结束的点,三点表示不包含结束的点。注意,..和...是运算符。
1..10
'a'..'z'
0...anArray.length

# 在Ruby里面的range是对象,他包含了开始和结束的对象;和Lisp里面的list表示不一样,但是可以使用to_a方法来转换成list(也就是array)。
(1..10).to_a » [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 要实现range的对象
class VU
include Comparable

attr :volume

def initialize(volume) # 0..9
@volume = volume
end

def inspect
'#' * @volume
end

# Support for ranges
def <=>(other)
self.volume <=> other.volume
end
def succ
raise(IndexError, "Volume too big") if @volume >= 9
VU.new(@volume.succ)
end
end

# range作为条件表达式来使用(这个现在还不太明白)
while gets
print if /start/../end/
end

# range作为interval的用法(也就是看某个元素是否在一个区间之内)
(1..10) === 5 » true
(1..10) === 15 » false

  • Regex(正则表达式)可以用3种方式来创建。
a = Regexp.new('^/s*[a-z]')   	»  	 /^/s*[a-z]/  # 直接使用类的new方法
b = /^/s*[a-z]/ » /^/s*[a-z]/ # 使用//literal
c = %r{^/s*[a-z]} » /^/s*[a-z]/ # 使用%r{}的方式
  • 匹配Regex可以使用Regexp或者String类的match函数来匹配,或者使用=~(匹配)和!~(不匹配)操作符来匹配。其中如果操作符两边 都是字符串的话,那么在右边的字符串会转化成Regexp对象。这些比较返回的都是匹配字符串在原串中的位置;如果不匹配则返回nil。
a = "Fats Waller"
a =~ /a/ » 1
a =~ /z/ » nil
a =~ "ll" » 7
  • 在每次匹配之后,有3个全局变量会被设置。$& 存放的是匹配的串;$` 匹配串前面的串;$' 匹配串后面的串
  • Anchor的意思是把正则表达式的匹配范围固定在某个地方。'^'匹配'行 '的开头,'$'匹配行的结尾,'/A'匹配字符串的开头,'/z'和'/Z'匹配字符串的结尾。具体的区别可以看下面的例子:
# 主要的区别在于如果字符串中包含/n(换行符)
showRE("this is/nthe time", /^the/) » this is/n<<the>> time
showRE("this is/nthe time", /is$/) » this <<is>>/nthe time
showRE("this is/nthe time", //Athis/) » <<this>> is/nthe time
showRE("this is/nthe time", //Athe/) » no match
  • '/b'匹配词的边界,'/B'匹配非(词边界).
  • []之间表示一个character class,在里面出现的字符会用作为集合来匹配一个字符。当出现平常的escape字符的时候,仍然会正常进行替换(也就是[/n]表示一个包含 newline的集合)。下面是Ruby提供的常用的character class缩写。
Character class abbreviations
Sequence As [ ... ] Meaning
/d [0-9] Digit character
/D [^0-9] Nondigit
/s [/s/t/r/n/f] Whitespace character
/S [^/s/t/r/n/f] Nonwhitespace character
/w [A-Za-z0-9_] Word character
/W [^A-Za-z0-9_] Nonword character

#注意,'.'号在Regexp里面一般是匹配除了/n之外的任何字符,除非是在multiline的模式下。
  • 重复匹配表达式的用法如下,假设r是一个正则表达式:
r  *   	matches zero or more occurrences of r.
r + matches one or more occurrences of r.
r ? matches zero or one occurrence of r.
r {m,n} matches at least ``m'' and at most ``n'' occurrences of r.
r {m,} matches at least ``m'' occurrences of r.
  • 一个改变重复匹配行为的例子,一般的重复匹配都会尽量的匹配多的字符,比如如果用/ab*a/匹配abbabba的话,那么我们会得到abbabba。但 是如果想要得到的是abba的话,那么可以用?(问号)来修饰。这样匹配出来的字符串会先看后面的Regexp,如果有匹配,则马上停止匹配。如果在上面 的例子中,当遇到第一个a后面的a时,就会马上停止匹配,所以我们就能得到abba。
showRE("The moon is made of cheese", //s.*?/s/)   	»  	 The<< moon >>is made of cheese
  • 注意在Regexp里面的操作符是有优先级的,比如说'|'和*的优先级就不一样。如果我们想要改变优先级的顺序的话,那么就要使用grouping。grouping的时候使用括号()来将想要改变优先级的Regexp括起来。
a = 'red ball blue sky'
showRE(a, /blue|red/) » <<red>> ball blue sky
showRE(a, /(blue|red) /w+/) » <<red ball>> blue sky # 注意这里如果不用括号的话,那么就是匹配blue或者red /w+。
  • 括号()还可以用来在Regexp里面或外面获取匹配出来的串。这样就可以用来匹配重复的串。如果在串里面引用,则用/1,/2,……来引用。如果在串外 面引用,则用$1,$2,……来引用匹配的串。而且要注意,Ruby是会数openning left parentheses的,所以如果多层嵌套的话,要注意left parentheses的顺序,看下面的例子:
"12:50am" =~ /((/d/d):(/d/d))(..)/   	»  	 0  #这里第一个(是最外层的,所以$1是指整个时间。
"Time is #$1" » "Time is 12:50"
"Hour is #$2, minute #$3" » "Hour is 12, minute 50"
"AM/PM is #$4" » "AM/PM is am"

# 重复匹配的例子
showRE('He said "Hello"', /(["']).*?/1/) » He said <<"Hello">>
  • Regexp的替换使用String#sub和String#gsub函数。arg1是用来匹配的Regexp,arg2是用来替换的串,arg2也可以 是code block,他的返回值用来替换匹配的串。这两个函数是不会改变原来的string的,而String#sub!和String#gsub!是改变原来的 串。
a = "the quick brown fox"
a.sub(/^./) { $&.upcase } » "The quick brown fox"
a.gsub(/[aeiou]/) { $&.upcase } » "thE qUIck brOwn fOx"
  • 在替换中,arg2也是可以使用/1,/2这些用来的Regexp里面来指代匹配的串的变量。其他可以用在替换串中的特殊字符:
/1, /2, /3 .... (first match, second match, third match, ...)
/& (last match)
/+ (last matched group)
/` (string prior to match)
/' (string after match)
// (a literal backslash).
  • 在Ruby里面的Regexp是一个类,他的match方法就是类似于=~。match返回的是nil当没有匹配,MatchData当有匹配。这个MatchData就 包含了有匹配里面所需要用到的信息。之前看到的$变量($&, $1这些)实际上只是从这个变量里面抽取出值来封装而已。当match匹配的时候,他会同时将这个结果存放在$~这个thread local的变量里面,然后$变量就会从$~里面抽取信息进行封装。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值