Thursday, October 16, 2008

(11)字符串截取和查询操作

也许String对象最重要的操作就是通过[]下标访问操作了,你可以通过这种方式提取字符串内容或者更改字符串内容。在Ruby1.8中字符串被当作一个字节或者8位的字符码数组,你可以通过length或者size方法获得这个数组的长度,你通过在[]设置索引数字来设置或者得到那个位置的值:
s = 'hello';   # Ruby 1.8
s[0] # 返回值为104,第一个字母'h'的ASCII码
s[s.length-1] # 返回值为111,最后一个字母'o'的ASCII码
s[-1] # 返回值为111,你可以使用负数索引
s[-2] # 返回值为108,倒数第二个字母'l'的ASCII码
s[-s.length] # 104: 另一种访问第一个字符的方式
s[s.length] # nil: 如果超出索引范围就返回nil

注意的一点是,索引是正向从0开始的,如果你使用负数索引那么最后一个字母是从-1开始索引的。而且,在Ruby中如果你给出了一个超出索引范围的下标,Ruby不会抛出异常,而是返回一个nil。
在Ruby1.9中返回值为一个字符串,而不是字符的编码:
s = 'hello';   # Ruby 1.9
s[0] # 返回'h'
s[s.length-1] # 返回'o'
s[-1] # 返回'o'
s[-2] # 返回'l'
s[-s.length] # 返回'h'
s[s.length] # nil:如果超出索引范围就返回nil

如果要修改字符串内容,只要给相应位置赋值就可以了,Ruby1.8中你可以使用字符编码或者字符串作为赋值内容,在Ruby1.9中你应该使用字符串:
s[0] = ?H        # 将第一个字符替换为大写的H
s[-1] = ?O # 将最后一个字符替换为大写的O
s[s.length] = ?! # 这里会出现异常,因为你的赋值超出了索引的访问

等号右边可以是任意的字符串,多字节字符串也是允许的,或者是一个空的字符串,一下代码在Ruby1.8和1.9都可以正常运行:
s = "hello"      # 初始化字符串
s[-1] = "" # 删除最后一个字符,现在s的值为hell
s[-1] = "p!" # 修改最后一个字符现在s的值为 "help!"

大多数情况下,你需要取得的是字符串中的一段内容,而不是一个单独的字符。要截取字符串中的一段内容你可以在[]中给出两个用逗号隔开的数字,通过这种方式你就可以得到一段文本了。其中第一个数字指出了我们要截取的文本从哪个位置开始索引,第二个字符指出了我们要截取的内容的长度:
s = "hello"
s[0,1] = "H" # 将第一个字符替换为一个大写的H
s[s.length,0] = " world" # 在字符我末尾增加其他的字符串
s[5,0] = "," # 在字符串中插入一个逗号
s[5,6] = "" # 通过给一段文本赋值空文本的方式来删除那段文本,现在s == "Hellod"

另一种截取或者插入、删除、修改字符串的方式是使用Range(范围)对象,Range对象通过两个数字之间插入两个联系的点号表示,比如1..3表示范围在1到3之间。

s = "hello"
s[2..3] # "ll": 位于索引2到3的字符
s[-3..-1] # "llo": 负数索引页可以使用
s[0..0] # "h": Range只包含一个字符
s[0...0] # "": 空的Range对象
s[2..1] # "": 这也是空的Range
s[7..10] # nil: 这个Range超出了索引范围,所以返回nil
s[-2..-1] = "p!" # 替换值,现在s=="help!"
s[0...0] = "Please " # 在起始位置插入新值,现在s== "Please help!"
s[6..10] = "" # 删除值,现在s== "Please!"

注意的一点是,用逗号分隔的方式,分别指出了索引的开始位置和截取字符的长度,而使用Range对象是制定了一段索引的范围,两者是不同的。
另外,你还可以使用字符串作为索引,当你这样做的时候,你得到的是字符串中包含这个字符的第一个,如果查找不到你给出的字符,就返回一个nil对象:

Created with colorer-take5 library. Type 'ruby'

s = "hello"
while(s["l"]) # 循环判断是否包含字符 "l"
s["l"] = "L"; # 将找到的字符从 "l" 替换为 "L"
end # 现在s=="heLLo"

最后要说的是,你还可以在[]中包含正则表达式,这样会得到一个符合正则表达式的内容:


s[/[aeiou]/] = '*'
# 将找到的第一个原音替换为星号


No comments: