第12章 字符串
建立字符串
1. 建立字符串最简单的方法,是直接在程序里将表示字符串对象的“一连串文字”以“""”或“''”直接括起来。
moji = "字符串" str1 = "这也是#{moji}" p str1 #=> "这也是字符串" str2 = '这也是#{moji}' p str2 #=> "这也是#{moji}" |
使用“""”的时候,字符串中用“#{}”框住的部分会当做Ruby语句执行,并将运行结果插入。这称为内嵌表达式。 |
另外,使用“""”时,还可以插入以“\”开头的特殊字符
特殊字符 |
意义 |
特殊字符 |
意义 |
\t |
定位 (0x09) |
\f |
换页(0x0c) |
\n |
换行(0x0a) |
\b |
退位(0x08) |
\r |
归位(0x0d) |
\a |
哔声(0x07)(注:系统发声) |
\e |
忽略(0x1b)(Escape键) |
\s |
空白(0x20) |
\v |
垂直定位(0x0b) |
\nnn |
以八进制表示字符(n取0~7) |
\xnn |
以十六进制表示字符(n取0~9、a~f、 A~F) |
\cx\C-x |
Ctrl + X |
\M-x |
Meta (Alt) + X |
\M-\C-x |
Meta (Alt) +Ctrl + X |
\x |
字符x本身(x是上述字符以外的字符) |
2. 使用%Q、%q
desc = %Q{Ruby的字符串可以使用“""”与“''”。} str= %q |Ruby said, 'Hello world!'| |
当想要建立的字符串含有“”与“”等字符时,可以使用%Q与%q。 |
3. 使用嵌入文档
嵌入文档(Here Document)是源自UNIX shell的写法,使用“<<”来建立字符串。想要建立中间有换行的多行字符串时,这个方法最简单。
message<<"结束记号" 可内嵌的字符串 结束记号 |
“<<”后面紧接的结束记号,可以写成“''括住的字符串”或“""括住的字符串”(默认值),使用“""”时,整个字符串内的特殊字符与内嵌表达式都会被解释;使用“''”则字符串会原封不动。 |
经常使用的结束记号有“EOF”与“EOB”。“EOF”是“End of File”的简写,EOB是“End of Block”的简写。
Here Document最后面的结束记号一定要从行头写起。若在程序代码里缩排使用了Here Document,则可以将“<<”改写成“<<-”。
4. 使用sprintf方法
若要使用八进制或十六进制表示数值,或者要建立遵守某种格式的字符串时,会使用sprintf方法。
n = 123 printf("%04d\n", n) #=> 0123 n = "Ruby" printf("Hello, %8s!\n",n) #=> Hello, Ruby! ## 向右靠齐 printf("Hello, %-8s!\n", n) #=>Hello, Ruby ! ##向左靠齐 |
printf是进行画面输出的方法,起到同样效果但输出结果是字符串对象的方法是sprintf。sprintf常常用于那些使用字符串类方法来处理生成不规则的字符串的场合。
获取字符串长度
可以使用length方法或size方法,两者的结果都一样(返回字符串的字节数)。
使用正则表达式,可以正确地获取中文或日文字符串的字数。
p '面向对象程序语言'.split(//u).length #=> 8 |
当字符串是UTF-8编码时 |
p '面向对象程序语言'.split(//e).length #=> 8 |
当字符串是繁体中文的Big5编码时,因Big5码与日文EUC-JP编码的码位较为类似,故可变通处理。 |
p "".empty? #=> true |
empty?方法可以用来检查字符串长度是不是0 |
分割字符串
以特定的字符分割字符串 |
str = "Hello world:thank you:2012:USA" column = str.split(/:/) p column #=> ["Hello world", "thank you", "2012", "USA"] |
|
将字符串以特定字数分割 |
str = "Ruby In A Nutshell Yukihiro Matsumoto 2001USA" column = str.unpack("a20a20a4a*") p column #=> ["Ruby In A Nutshell ", " Yukihiro Matsumoto ", "2001", "USA"] |
unpack方法原来是pack方法的相反功能,pack用来将数组对象转换成二进制数据,而unpack则是将二进制数据复原成数组的方法。然而,当每段字符串的长度固定时,也可以作为将字符串分割成数组的功能使用。 |
unpack方法的语法: data.unpack(描述要分割的方式)
在将字符串分割成数组时,描述要分割的方式的地方指定的是“a分割的字节数”。
链接字符串
将两个字符串连接起来,建立新字符串 (用“+”) |
hello = "Hello," world = "World!" str = hello + world p str #=> "Hello, World!" |
将现有的字符串接上字符串,称为更长的字符串 (用<<方法或concat方法) |
hello = "Hello" world ="World!" hello << world p hello #=> "Hello, World!" hello.concat(world) p hello #=> "Hello, World!World!" |
字符串的索引
str = "abcde" p str[0] #=> 97 p str[0].chr #=> "a" |
字符串索引所返回的对象,并不是“字符串”而是“字码”,是一个数值。 |
str = "甲乙丙丁戊" p str.split(//u)[2] #=>"丙 |
索引是以字节换算的,想要获取中文字符时,必须结合split方法使用(split方法的实参,当字符编码是Shift_JIS时使用“//s”;是UTF-8时使用“//u”;是EUC-JP时则使用“//e”。 |
str = "甲乙丙丁戊" p.str[3,6] #=> "乙丙" |
与数组相同,也可以一次获取特定的长度。这时返回值就直接是字符串对象,当然索引值单位也是字节。 使用Big5编码时,一个汉字为两个字节;使用UTF-8编码时,一个汉字为3个字节。 |
比较两个字符串是否相等,可以使用“==”与“!=”。
处理换行字符
|
必须删除一个字符 |
只删除换行字符 |
|
非破坏性的 |
chop |
chomp |
|
破坏性的 |
chop! |
chomp! |
|
while line = gets line.chomp! 处理line的内容 end |
基本上是个固定写法 |
||
查找字符串
str = "sumomomomomomomouchi" p str.index("momo") #=> 2 p str.rindex("momo") #=> 12 |
index方法从左边开始查找,rindex方法从右边开始查找。找到时,会返回其所处的位置。未找到时,返回nil。 |
str = "sumomomomomomomouchi" p str.include?("momo") #=> true |
只想检查是否包含时,可使用include?方法 |
替换字符串
Ruby有sub与gsub这两个方法用来做替换的操作,这两个方法的区别在于sub方法是取代最先找到的地方,而gsub方法会取代所有找到的地方。另外,sub方法与gsub方法还有破坏性的版本sub!与gsub!方法。
字符串与数组共同的方法
除了Object类的实例方法,还有以下这些方法也是共有的:
1) 用来操作索引的方法
2) 与Enumerable模块相关的方法
3) 连接、逆转相关的方法
s[n] = str s[n..m] = str s[n, len] = str |
将字符串的一部分替换成str |
s[n].slice!(n) s.slice!(n..m) s.slice!(n, len) |
删除字符串s的一部分,注意方法的返回值是删除的部分。 |
连接、逆转相关的方法
连接 |
删除 |
逆转 |
s.concat(s2) s+s2 |
s.delete(str) s.delete!(str) |
s.reverse s.reverse! |
其它方法
清除s前后空白 |
将s全部大(小)写 |
将s的大小写互换 |
将s的首字母大写 |
s.strip s.strip! |
s.upcase s.upcase! s.downcase s.downcase! |
s.swapcase s.swapcase! |
s.capitalize s.capitalize! |
s.tr s.tr! |
p "abcdefg".tr("b", "B") #=> "aBcdefg" p "abcdefg".tr("bc", "BC") #=> "aBCdefg" p "abcdefg".tr("b-e", "B-E") #=> "aBCDEfg" |
源自于UNIX指令tr的方法,用来替换字符。 语法:s.tr("a-z", "A-Z") tr方法无法使用正则表达式,也无法指定转换两个字以上的字符串。 |
转换字码
在Ruby中,实现文字编码变换的库文件有nkf库文件和iconv库文件。
nkf库文件由NKF模块提供。NKF模块原是用于UNIX而制作的nkf的过滤器指令。在NKF模块中,通过指定文件编码,使用类似命令行选项的字符串。如果预先没有指定输入文字的编码方式,NKF会自动判断其编码。作为独立的库文件,nkf不依赖于操作系统。
iconv库文件
iconv库由iconv类提供。iconv不能进行输入文字的编码的自动判别,因此输入文字和输出文字的编码格式都需要预先指定。iconv类功能与平台紧密相关,因此iconv库依赖于系统平台。也就是说,在不同的系统平台上,会出现同样的编码但名称不同的现象。
如果想知道iconv库能处理哪些文字编码,可以使用命令: iconv -1
require "iconv" result = "" cd = Iconv.open("UTF-8", "EUC-JP") result << cd.iconv("に") cd.close |
变换开始时,通过iconv.new方法生成变换器,然后在iconv里实施编码变换,最后返回变换的结果。变换器使用结束后需要用close方法关闭它。 |
require "iconv" result = "" cd = Iconv.open("UTF-8", "EUC-JP") {|cd| result << cd.iconv("に") } |
如果对File.open指定操作范围(注:{}中部分)的话,可以不需要close方法。 |
require "iconv" euc_str = "日本语EUC文字列" utf8_str = Iconv.conv("UTF-8", "EUC-JP", euc_str) |
可以不显示地生成变换器,直接使用Iconv.conv来完成编码变换。 |