第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来完成编码变换。