字符串
在这部分的教程将详细的介绍字符串。
字符串是计算机语言中最重要的数据类型之一,这就是为什么我们决定要用一整章来介绍字符串。
字符串是序列化的unicode字符。它是一种数据类型存储了序列化的值,它的元素通常代表的是根据字符编码的字符。当一个字符串在代码中以字面量出现,它也称为字符串文本。
第一个例子
在Ruby中字符串文本是以单引号或者双引号引起来的。
#!/usr/bin/ruby
# first.rb
puts ‘Python language’
puts “Ruby language”
这个例子有两个字符串,第一个是用单引号,另一个是用双引号。
$ ./first.rb
Python language
Ruby language
程序输出。
使用引号
如果我们想要显示引号该怎么做,直接引用?这有两种方法实现。
#!/usr/bin/ruby
puts “There are many stars”
puts “He said, \”Which one is your favourite?\””
puts ‘There are many stars’
puts ‘He said, “Which one is your favourite?”‘
我们使用()字符将引号转义。通常双引号是用于划定字符串的范围,然后被转义之后它原始的意义就没有了。它在字符串中被作为一个正常的字符。第二种方法是混合使用单引号和双引号。
$ ./quotes.exe
There are many stars.
He said, “Which one is your favourite?”
输出结果。
转义序列
转义符是特殊的字符,在字符串中有特殊的含意。
#!/usr/bin/ruby
puts “one two three four”
puts “one\ntwo\nthree\nfour”
最常用一个的转义符是换行符\n。它在许多编程语言中都有效。换行符之后的字符将出现在新的一行。
$ ./newline.rb
one two three four
one
two
three
four
以上脚本的输出结果中换行符之后的字符在新的一行。
r、b和t是正常的字符,当前面加上\字符后就具有特殊意义了。
#!/usr/bin/ruby
puts “ bbb\raaa”
puts “Joan\b\b\bane”
puts “Towering\tinferno”
这个例子中我们用到了三个不同的转义字符。
puts “ bbb\raaa”
回车符\r控制之后的字符回到行首。之前打印到终端上的字符串会被处理。这个转义字符会将aaa字符位于bbb之前,输出为aaabbb。
puts “Joan\b\b\bane”
\b是退格控制符,它会删掉前一个字符。这个字符串将在终端上打印‘Jane’而不是‘Joan’。
puts “Towering\tinferno”
最后\t转义符是用于两个词之间制表空格的。
$ ./escapes.rb
aaabbb
Jane
Towering inferno
例子的输出结果。
反斜杠\是用于创建转义符的特殊字符。当需要打印反斜杠时,则在它前面加上另一个反斜杠。这意味着转义过了可以打印。在Ruby中单引号和双引号用于划定字符串范围的,想要打印它们同样也需要在前面加上\。
#!/usr/bin/ruby
puts “The special character \“
puts “The special character \’”
puts “The special character \””
这个例子中我们在终端上打印了这三个字符。
$ ./specials.rb
The special character \
The special character ‘
The special character “
输出结果。
访问字符串的元素
在Ruby中我们可以使用方括号[]来访问字符串的元素。在括号内可以使用字符串、范围索引。
#!/usr/bin/ruby
msg = “Ruby language”
puts msg[“Ruby”]
puts msg[“Python”]
puts msg[0]
puts msg[-1]
puts msg[0, 3]
puts msg[0..9]
puts msg[0, msg.length]
这个例子的代码展示了我们可以访问字符串的一部分。
msg = “Ruby language”
这里是我们将要访问的字符串。
puts msg[“Ruby”]
这行代码我们测试字符串‘Ruby’是否是msg的子串。如果是将返回该字符串。
puts msg[0]
可以通过索引来访问这个字符串的字符。编号是从0开始的,也就是说0号索引是第1个字符。msg[0]返回字符串的第一个字符R。
puts msg[-1]
这里我们访问最后一个字符。-1代表了最后一个索引。
puts msg[0, 3]
两个用逗号分隔的索引返回了从第1个索引开始到第2个索引的字符,不包括第2个索引。
puts msg[0..9]
范围操作符也可以完成同样操作。这里我们打印前10个字符。
puts msg[0, msg.length]
这行返回全部的字符。msg.length返回字符串的长度。
$ ./access.rb
Ruby
R
e
Rub
Ruby langu
Ruby language
输出结果。
多行字符串
许多编程语言要创建多行字符串需要额外的努力,在Visual Basic中尤其如此。但是在Ruby中却是很容易。
#!/usr/bin/ruby
puts “I hear Mariachi static on my radio
And the tubes they glow in the dark
And I’m there with her in Ensenada
And I’m here in Echo Park
“
puts %/
Carmelita hold me tighter
I think I’m sinking down
And I’m all strung out on heroin
On the outskirts of town/
puts <<STRING
Well, I’m sittin’ here playing solitaire
With my pearl-handled deck
The county won’t give me no more methadone
And they cut off your welfare check
STRING
这个例子中我们使用了Carmelita歌曲的歌词。我们展示了使用三种方法打印多行字符串。可以使用双引号;可以使用%字符创建多行字符串,用%后面的字符将字符串包围住;最后我们使用定界符,这和语法是使用<<接着一些字符串,用这个字符串包围住多行字符。它必须左对齐。
变量替换
变量替换是将字符串的变量替换成它们的值。为了将变量替换成值,这个变量在字符串需要放在#{和}之间。
#!/usr/bin/ruby
name = “Jane”
age = 17
puts “#{name} is #{age} years old”
这个例子中我们替换了字符串中的两个变量:name和age。
$ ./interpolation.rb
Jane is 17 years old
也可以替换表达式。
#!/usr/bin/ruby
x = 5
y = 6
puts “The product of #{x} and #{y} is #{xy}”
这是一个表达式替换的例子。
$ ./interpolation2.rb
The product of 5 and 6 is 30
运行例子脚本。
这是另一种替换变量的方法。类似于Python 2.x所支持的替换。
#!/usr/bin/ruby
name = “Jane”
age = 17
message = “%s is %d years old” % [name, age]
puts message
以上是一个例子。
message = “%s is %d years old” % [name, age]
使用之前先创建一个字符串。%s和%d是格式化字符,分别表示字符串和数字。值由%字符后面的方括号提供。
字符串连接
字符串连接是从多个字符串创建一个字符串。
#!/usr/bin/ruby
lang = “Ruby” + “ programming” + “ languge”
puts lang
lang = “Python” “ programming” “ language”
puts lang
lang = “Perl” << “ programming” << “ language”
puts lang
lang = “Java”.concat(“ programming”).concat(“ language”)
puts lang
Ruby提供多种方法连接字符串。
lang = “Ruby” + “ programming” + “ languge”
在计算机语言中加法操作符是最常用的一种。Perl和PHP是用的点操作符(.)。
lang = “Python” “ programming” “ language”
Ruby自动连接多个后续的字符串。
lang = “Perl” << “ programming” << “ language”
另一种方法是使用<<操作符。
lang = “Java”.concat(“ programming”).concat(“ language”)
每个字符串字面符实际上都是一个对象。我们可以对Ruby对象调用很多方法。对于字符串对象可以调用concat方法连接两个字符串。它返回最后的结果对象,再对其调用另一个方法。这样我们就将这些方法链接起来了。
$ ./concatenate.rb
Ruby programming languge
Python programming language
Perl programming language
Java programming language
输出结果。
冻结字符串
在Java或者C#中字符串是不可变的,这意味着不能修改已存在的字符串。只能通过已存在的字符串创建一个新的。在Ruby中字符串同样也是不可修改的。
Ruby中字符串对象有一个freeze方法,可以使它们不可变。
#!/usr/bin/ruby
msg = “Jane”
msg << “ is “
msg << “17 years old”
puts msg
msg.freeze
#msg << “and she is pretty”
这个例子我们演示了字符串是可变的。然后在调用freeze方法之后我们就不能再作修改了。如果我们取消掉注释将会得到’can’t modify frozen string’错误信息。
字符串比较
在编程中字符串比较是件平常的事情。我们可以使用==操作符或者eql?方法来比较两个字符串,如果相等返回true,否则false。
#!/usr/bin/ruby
puts “12” == “12”
puts “17” == “9”
puts “aa” == “ab”
puts “Jane”.eql? “Jan”
puts “Jane”.eql? “Jane”
这个例子的代码我们比较了一些字符串。
puts “12” == “12”
这两个是相等的,这行返回true。
puts “aa” == “ab”
第一个字符是相等,然后比较下一个字符。它们不同,因此返回false。
puts “Jane”.eql? “Jan”
eql?方法用于比较两个字符串。所有对象都内建了eql?方法。这个方法将另一个要比较的字符串作为参数传入。
$ ./comparing.rb
true
false
false
false
true
程序输出结果。
Ruby中有一个“飞船(spaceship)”操作符<==>。这个操作符来自Perl,与以上两个比较方法不同,它不是返回true和false,而是返回1、0或者-1。取决于左参数和右参数的关系。如果左参数大于右参数则返回1;如果左参数小于右参数则返回-1;如果相等返回0。什么才是一个字符大于另一个字符呢?字符在表中是有序的,在表中每个字符有一位位置。当比较字符时实际比较它们在表中的位置。例如ASCII表,字符a在b的前面,因此a<==>b返回-1,因为左参数的位置小于右参数b。
#!/usr/bin/ruby
puts “a” <==> “b”
puts “b” <==> “a”
puts “a” <==> “a”
使用“飞船”操作符比较字符串。
$ ./spaceship.rb
-1
1
0
输出结果。
有可能比较字符串不管大小写。在Ruby中有casecmp方法。这个方法与飞船操作符相同。
#!/usr/bin/ruby
puts “Jane”.casecmp “Jane”
puts “Jane”.casecmp “jane”
puts “Jane”.casecmp “Jan”
以上是一个例子。
puts “Jane”.casecmp “Jane”
puts “Jane”.casecmp “jane”
这两行返回结果都是0.因为我们不考虑字符的大小写。
$ ./case.rb
0
0
1
输出结果。
字符串对象
Ruby是面向对象语言。对象是面向对象程序的基本代码块。字符串也是对象。对象由数据和方法组成。在面向对象程序中,创建对象并且相互通信。
#!/usr/bin/ruby
website = “google.com”
puts website
website = String.new “zetcode.com”
puts website
以上例子我们展示了两个创建字符串的基本方法。
website = “google.com”
这里是使用字符串字面量创建了一个website字符串变量。
website = String.new “zetcode.com”
这是标准创建字符串对象的方法。然而第一和更常用,因为它更简洁,并且在计算机语言中更普遍。
#!/usr/bin/ruby
puts “zetcode”.upcase
puts “zetcode”.size
puts “zetcode”.reverse
这个例子中我们对字符串字面量调用了三个方法。如果是熟悉Java或者C的人可能会困惑。在Ruby中调用方法时字符串字面量会转化为一个字符串对象。
$ ./stringobject2.rb
ZETCODE
7
edoctez
输出结果。
字符串方法
Ruby字符串对象有一些有用的方法。如我们见到过的concat或者eql?。
#!/usr/bin/ruby
word = “Determination”
puts “The word #{word} has #{word.size} characters”
puts word.include? “tion”
puts word.include? “tic”
puts
puts word.empty?
word.clear
puts word.empty?
创建一个字符串变量,展示了四个字符串的方法。
puts “The word #{word} has #{word.size} characters”
size方法返回字符串的长度。
puts word.include? “tion”
include?方法判断一个字符串是否为子串。这里返回的是true。
puts word.empty?
word.clear
empty?方法检查字符串是否为空。返回一个布尔值。clear方法清空字符串。
$ ./basicmethods.rb
The word Determination has 13 characters
true
false
false
true
输出结果。
接下来的例子介绍字符串大小写的方法。
#!/usr/bin/ruby
ruby = “Ruby programming language”
puts ruby.upcase
puts ruby.downcase
puts ruby.capitalize
puts ruby.swapcase
Ruby中有四个与大小写相关的方法。upcase方法将字符串全转为大写并返回一个新对象;downcase方法是将字符串全转为小写并返回一个新对象;capitalize方法是将字符串的首字母大写并返回一个新的对象。最后swapcase方法是将大小写反转并返回一个新对象。
$ ./rubylang.rb
RUBY PROGRAMMING LANGUAGE
ruby programming language
Ruby programming language
rUBY PROGRAMMING LANGUAGE
输出结果。
接下来展示两个Ruby字符串的方法:start_with? 和end_with?。这两个方法都是返回布尔值。它们判断一个字符串是否分别以另一个字符串开头或结尾。
#!/usr/bin/ruby
ws1 = “zetcode.com”
ws2 = “www.gnome.org”
puts ws1.start_with? “www.”
puts ws2.start_with? “www.”
puts
puts ws1.end_with? “.com”
puts ws2.end_with? “.com”
这是一个上述方法的例子。
puts ws1.start_with? “www.”
这里检查一个字符串是否以“www.”开头。如果不是则在终端打印false。
puts ws1.end_with? “.com”
检查字符串ws1是否以”.com”结尾。如果是则在终端打印true。
$ ./startend.rb
false
true
true
false
输出结果。
接下来我们介绍inspect方法。这个方法返回被引号包围原始的字符串,对于特殊字符不处理。对于想要检查字符串由哪些字符组成的比较有用。
#!/usr/bin/ruby
msg = “Jane\t17\nThomas\t23”
puts msg
puts msg.inspect
inspect方法的一个例子。
msg = “Jane\t17\nThomas\t23”
这个字符串有一些特殊的字符。
puts msg
puts msg.inspect
第一种情况,字符串中的制表符和换行符被解释了。第二种情况我们得到了一个原始格式的字符串。
$ ./inspectmethod.rb
Jane 17
Thomas 23
“Jane\t17\nThomas\t23”
输出结果。
chomp方法是将字符串尾部的分隔符去掉并返回一个新对象。默认的分隔符是换行符(\n)。
#!/usr/bin/ruby
print “Are you sure to download? (Yes/No) “
response = gets
if (response.downcase == “yes”)
puts “Downloaded”
else
puts “Download cancelled”
end
puts response.inspect
上面的脚本我们从用户输入一些内容,然后再返回给用户。
$ ./chomp.rb
Are you sure to download? (Yes/No) Yes
Download cancelled
“Yes\n”
这个脚本没有正确的工作。原因很清晰,由inspect返回了。用户输入的内容以回车键结尾,因此换行符也被包含其中了。”Yes”与”Yes\n”不相等。要使用脚本正确运行,我们使用chomp方法移除掉换行符。
#!/usr/bin/ruby
print “Are you sure to download? (Yes/No) “
response = gets
if (response.downcase.chomp == “yes”)
puts “Downloaded”
else
puts “Download cancelled”
end
puts response.inspect
这个是正确的脚本。
if (response.downcase.chomp == “yes”)
这里我们在比”Yes”比较之前对输入内容进行了处理。
$ ./chomp.rb
Are you sure to download? (Yes/No) Yes
Downloaded
“Yes\n”
现在脚本正确工作了。
格式化字符串
Ruby中有格式化说明符。格式化说明符决定了如何显示一个字符串。它以%字符开始。格式化说明符放在单引号或者双引号内。
格式化说明符有以下字段。
%[flags][field width][precision]conversion specifier
方括号内的字段是可选的。
转换说明符表明数据将如何进行转换。
#!/usr/bin/ruby
puts “There are %d oranges in the basket.” % 12
puts “There are %d oranges and %d apples in the basket.” % [12, 10]
这是一个格式化说明符的例子。
puts “There are %d oranges in the basket” % 12
当我们在字符串中使用%d,我们在这个位置将期望一个数字。d是十进制数的转换说明符。这个数据在%字符后面给出。
puts “There are %d oranges and %d apples in the basket” % [12, 10]
当我们在一个字符串中使用多个格式化说明符时,每个都以%开始。多个值放在[]之间并以逗号分隔。
$ ./formatspecifiers.rb
There are 12 oranges in the basket.
There are 12 oranges and 10 apples in the basket.
输出结果。
接下来的例子我们介绍一些基本的转换符。
#!/usr/bin/ruby
puts “There are %d apples.” % 5
puts “I can see %i oranges.” % 3
puts “The width of iPhone 3G is %f mm.” % 62.1
puts “This animal is called a %s” % “rhinoceros.”
我们使用了整数、浮点数和字符串的转换符。
puts “There are %d apples.” % 5
puts “I can see %i oranges.” % 3
d和i都是用于整数。
puts “The width of iPhone 3G is %f mm.” % 62.1
f用于浮点数。默认浮点数有6个小数。
puts “This animal is called a %s” % “rhinoceros.”
s用于字符串。
$ ./basicspecifiers.rb
There are 5 apples.
I can see 3 oranges.
The width of iPhone 3G is 62.100000 mm.
This animal is called a rhinoceros.
输出结果。
接下来是一个实践的例子。
#!/usr/bin/ruby
website = “zetcode.com”
website.each_char do |c|
print “#{c} has ASCII code %d\n” % c.ord
end
这个例子我们记遍历字符串的所有字符并在终端上打印它的ASCII值。
website.each_char do |c|
print “#{c} has ASCII code %d\n” % c.ord
end
each_char方法将website字符串中的每个字符传给代码块,一个字符是一次循环。当前的字符保存在这是c中。我们使用ord方法获取字符的ASCII值。
$ ./character.rb
z has ASCII code 122
e has ASCII code 101
t has ASCII code 116
c has ASCII code 99
o has ASCII code 111
d has ASCII code 100
e has ASCII code 101
. has ASCII code 46
c has ASCII code 99
o has ASCII code 111
m has ASCII code 109
输出结果。
数字有多种显示形式。
#!/usr/bin/ruby
# decimal
puts “%d” % 300
# hexadecimal
puts “%x” % 300
# octal
puts “%o” % 300
# binary
puts “%b” % 300
# scientific
puts “%e” % (5/3.0)
上面的例子中我们打印数字的十进制、十六进制、八进制、二进制和科学记数的形式。
# hexadecimal
puts “%x” % 300
x转换符用于将数字转为十六进制格式。
# binary
puts “%b” % 300
b转换符用于将数字转为二进制格式。
$ ./various.rb
300
12c
454
100101100
1.666667e+00
输出结果。
精度是格式化说明符的一个字段。它指明了后面小数点的位数。它对于整数、小数和字符串有不同的意义。当用于整数时表明了最少打印多少个数字。如果数字个数少于精度则前面用0补全。对于整数精度默认为1,表示前面没有0.当用于浮点数时表示小数点后显示多少个数字。最后,用于字符串时精度表示多少个字符会打印。
#!/usr/bin/ruby
puts ‘Height: %f %s’ % [172.3, ‘cm’]
puts ‘Height: %.1f %s’ % [172.3, ‘cm’]
puts “%d” % 16
puts “%.5d” % 16
puts “%s” % “zetcode”
puts “%.5s” % “zetcode”
这个例子中我们使用了精度字段。
puts ‘Height: %f %s’ % [172.3, ‘cm’]
puts ‘Height: %.1f %s’ % [172.3, ‘cm’]
172.3是一个浮点数。如果没有指定精度则会显示6个小数。这里将会显示5个0.第二行的.1是精度,它将小数个数减为1。的
puts “%d” % 16
puts “%.5d” % 16
对于整数默认精度为1。第二行中我们指明了精度为.5,这将会在16前面加上3个0。
puts “%s” % “zetcode”
puts “%.5s” % “zetcode”
第一行会打印所有的字符串。第二行仅打印5个,有两个字符将抛弃。
$ ./precision.rb
Height: 172.300000 cm
Height: 172.3 cm
16
00016
zetcode
zetco
输出结果。
宽度字段表示数据最小要显示的宽度。它是一个数字,并且在小数点之前。如果输出比较短,则会被用空格填充,且右对齐。如果宽度前面有减号则会左对齐。如果输出比宽度长则会完整输出。
#!/usr/bin/ruby
puts “%d” % 1
puts “%d” % 16
puts “%d” % 165
puts “%d” % 1656
puts “%d” % 16567
puts “%10d” % 1
puts “%10d” % 16
puts “%10d” % 165
puts “%10d” % 1656
puts “%10d” % 16567
第一种情况打印5个数字没有指明宽度。输出的宽度即为数字的位数。第二种情况指明宽度为10。则每个都最少输出10字符的长度,数字右对齐。
puts “%d” % 1
puts “%d” % 16
打印两个数字,输出的宽度分别为1、2个字符。
puts “%10d” % 1
puts “%10d” % 16
这里宽度都为10个字符。这两个数被填充了8、9个空格。
$ ./fieldwidth.rb
1
16
165
1656
16567
1
16
165
1656
16567
我们发现第二种情况数字是右对齐的。
标志修饰符修改了模式的行为。
#标志分别在二进制、八进制各十六进制前加上0b、0和0x。它会给小数加上小数点,即使这个小数人被精度限制了。
#!/usr/bin/ruby
puts “%#b” % 231
puts “%#x” % 231
puts “%#o” % 231
puts “%.0e” % 231
puts “%#.0e” % 231
puts “%.0f” % 231
puts “%#.0f” % 231
这个例子我们使用了#标志。
puts “%#b” % 231
puts “%#x” % 231
puts “%#o” % 231
十进制数231分别以二进制、八进制和十六进制打印。#标志会给它们加上前缀。
puts “%.0e” % 231
puts “%#.0e” % 231
这个.0限制了小数个数。然后使用#标志后小数点会显示,即使没有小数值。
$ ./flags1.rb
0xe7
0b11100111
0347
2e+02
2.e+02
231
231.
输出结果。
+标志会给正数加上正号。对于二进制、十六进制和八进制的负数会加上负号并使用它的绝对值。
#!/usr/bin/ruby
puts “%d” % 231
puts “%+d” % 231
puts “%d” % -231
puts “%+d” % -231
puts “%b” % -231
puts “%o” % -231
puts “%x” % -231
puts “%+b” % -231
puts “%+o” % -231
puts “%+x” % -231
一个演示+标志符的例子。
puts “%d” % 231
puts “%+d” % 231
通常正数的符号会被忽略掉。如果想要显示正数的符号可以使用+标志符。
puts “%d” % -231
puts “%+d” % -231
+标志符对负数没有影响,输出结果还是一样的。
puts “%b” % -231
puts “%o” % -231
puts “%x” % -231
二进制、八进制和十六进制的数有它们自己生成负数的方法。
puts “%+b” % -231
puts “%+o” % -231
puts “%+x” % -231
如果我们对负数指定了+标志,我们将数字转为不同的格式并加上负号。没有专门的方式表示负数。
$ ./flags2.rb
231
+231
-231
-231
..100011001
..7431
..f19
-11100111
-347
-e7
输出结果。
这里介绍0标志和-标志。0标志会用0代替空格来填充数字。-标志会将输出左对齐。
#!/usr/bin/ruby
puts “%010d” % 1
puts “%010d” % 16
puts “%010d” % 165
puts “%010d” % 1656
puts “%010d” % 16567
puts “%-10d” % 1
puts “%-10d” % 16
puts “%-10d” % 165
puts “%-10d” % 1656
puts “%-10d” % 16567
以上是一个例子。
puts “%010d” % 1
puts “%010d” % 16
数字会用0填充。
puts “%-10d” % 1
puts “%-10d” % 16
数字个数比宽度短,且会左对齐。
$ ./fieldwidth2.rb
0000000001
0000000016
0000000165
0000001656
0000016567
1
16
165
1656
16567
输出结果。
标志符用于精度和宽度。当我们使用符号时精度和宽度将作为一个参数。
#!/usr/bin/ruby
puts “%.f” % [3, 1.1111111]
puts “%0d” % [10, 2]
puts “%0.f” % [10, 3, 1.1111]
使用了标志的的例子。
puts “%.f” % [3, 1.1111111]
这里使用作为精度,则第一个数字3是精度的参数。它只为显示1.1111111的3个小数。
puts “%0d” % [10, 2]
这行的代码我们使用标志作为宽度。我们必须在[]之间加上宽度。第一个数字是宽度,第十个数字是要转换的值。
puts “%0.f” % [10, 3, 1.1111]
*标志可以同时用于宽度和精度。这样我们就必须都在[]中指明。
$ ./flags3.rb
1.111
0000000002
000001.111
输出结果。
这章的教程介绍的Ruby的字符串。
原文地址: http://zetcode.com/lang/rubytutorial/strings/
翻译:龙昌 admin@longchangjin.cn
完整教程:https://github.com/wusuopu/Ruby-tutorial