如何在Ruby中处理字符串
引言
一个字符串是由一个或多个字符组成的序列,这些字符可以是字母、数字或符号。
在Ruby中,字符串是对象,与其他语言不同的是,字符串是可变的,这意味着它们可以被就地修改,而不是创建新的字符串。
你在编写的每个程序中几乎都会使用到字符串。字符串可以用来显示和与用户进行文本通信。实际上,你正在阅读的页面就是通过网络浏览器在你的屏幕上显示的字符串构成的。字符串是编程中最重要的基础之一。
在这个教程中,您将学习如何在Ruby中处理字符串。您将创建字符串,将其显示在屏幕上,将其存储在变量中,将多个字符串连接在一起,还将学习如何处理特殊字符,如换行符、撇号和双引号。
创建并打印字符串
在Ruby中,字符串可以存在于单引号 ‘ 或双引号 ” 中,因此要创建一个字符串,需要将一系列字符包裹在其中之一中。
'This is a string in single quotes.'
"This is a string in double quotes."
您可以选择使用单引号或双引号。在大多数情况下,您选择哪种方式并不重要,只要保持一致即可。然而,使用双引号允许您进行字符串插值,这是您将在本教程中学习的内容。
要在程序中显示一个字符串,你可以使用print方法。
print "Let's print out this string."
打印方法会按照原样显示字符串。
试一试。在你的文本编辑器中创建一个名为print.rb的新的Ruby程序,并使用print方法打印三个字符串。
print 'This is the first string.'
print 'This is the second string.'
print 'This is the third string.'
保存文件并运行程序。
- ruby print.rb
你会看到以下的输出:
OutputThis is the first string.This is the second string.This is the third string.
不是将三个字符串分别打印到各自的行上,而是将这三个字符串一起打印到同一行上。打印方法会将字符串输出到屏幕上,但是如果你想让每个字符串显示在独立的行上,就需要自己添加换行符。
如果你想让这三个字符串分别显示在不同行上,请使用puts方法。修改你的程序,用puts代替print。
puts 'This is the first string.'
puts 'This is the second string.'
puts 'This is the third string.'
现在再次运行程序,就会看到以下输出结果。
OutputThis is the first string.
This is the second string.
This is the third string.
puts方法打印您指定的字符串,同时为您在字符串的末尾添加了换行符。
将字符串存储到变量中
变量是计算机内存中一个命名的引用位置。您可以使用变量来存储数据并在以后检索它。
要存储一个字符串到变量中,需要定义变量名并赋予字符串的值。
my_string = 'This is my string'
然后,要检索值,请使用变量的名称。
print my_string
要自己测试,请在您的编辑器中使用以下命令创建名为string_variables.rb的文件。
- nano string_variables.rb
然后添加以下代码
my_name = "Sammy the Shark"
my_age = "none of your business"
puts my_name
puts my_age
这个程序定义了两个变量:my_name和my_age。每个变量都被赋予了一个字符串。然后,我们使用puts方法将每个字符串分别打印在自己的一行上。
使用Ctrl + X和Y保存文件,然后执行程序。
- ruby string_variables.rb
您将看到以下输出:
OutputSammy the Shark
none of your business
通过给变量赋值字符串,您可以避免每次使用字符串时都要重复输入相同的字符串,从而更轻松地处理和操作程序中的字符串。
让我们来看看如何将字符串连接在一起创建新的字符串。
字符串连接 (String Concatenation)
连接意味着将两个或多个字符串连接在一起以创建一个新的字符串。为了进行连接,我们使用连接运算符,表示为加号(+)符号。当用于算术运算时,加号符号也是加法运算符。
这是如何将字符串sammy和shark连接在一起:
"sammy" + "shark"
这将产生以下的输出结果。
Outputsammyshark
连接将字符串拼接在一起,将它们合并并输出一个全新的字符串值。如果您想在单词sammy和shark之间添加空格,您需要在其中一个字符串中包含该空格,像这样:
"sammy " + "shark"
现在,在程序中你不会真的像这样写代码,但你经常需要将字符串和变量混合在一起,这就是拼接的地方。
这里举个例子:
color = "Blue"
print "My favorite color is " + color
这将导致输出为“我的最喜欢的颜色是蓝色”。请注意,在字符串中的单词“is”后面留有一个空格,这样输出中字符串和变量值之间就会有一个空格。
你可以通过这种方法将多个字符串连接在一起。创建文件concatenation.rb,并添加以下代码:
my_name = "Sammy the Shark"
my_age = "none of your business"
puts "My name is " + my_name + " and my age is " + my_age + "."
此程序定义了两个变量:my_name和my_age,每个变量都带有其自己的字符串,就像您之前做过的那样。但是这一次,我们不是打印变量的值,而是打印一个使用串联将这些值与一些上下文一起打印的字符串。
当你运行这个程序时,你会看到以下的输出结果。
OutputMy name is Sammy the Shark and my age is none of your business.
在这个小程序中,你使用了字符串连接将变量插入到这个字符串中。
当你通过串联将两个或多个字符串组合时,你正在创建一个新的字符串,你可以在整个程序中使用,所以你可能希望将你创建的字符串分配给一个新的变量,以便以后可以使用它。
my_name = "Sammy the Shark"
my_age = "none of your business"
# assign concatenated string to variable
output = "My name is " + my_name + " and my age is " + my_age + "."
# Print the output.
puts output
在像这样的小程序中,使用额外的输出变量可能是不必要的。但是在较大的程序中,您可能希望使用串联创建一个字符串,并在多个地方使用该字符串。另外,将数据处理(如串联和算术)与输出分开是一个好习惯,因为随着程序的扩大,您可能希望将逻辑和输出分开到不同的文件或组件中,以便更容易管理。
确保不要在两个不同的数据类型之间使用+操作符。比如,你不能将字符串和整数连接在一起。
为了看到发生了什么,创建一个名为strings_and_integers.rb的新程序,内容如下:
1. 字符串和整数.rb
2. 字符串与整数.rb
my_name = "Sammy the Shark"
my_number = 27
print my_name + my_number
这次我们有一个变量my_name,它存储了字符串”Sammy the Shark”,还有一个变量my_number,它存储了整数27。我们知道27不是一个字符串,因为它没有被引号包围。它也没有小数点,所以我们知道它是一个整数。
如果你运行这个程序:
- ruby strings_and_ints.rb
你会看到这个错误信息。
Outputstrings_and_ints.rb:4:in `+': no implicit conversion of Integer into String (TypeError)
from strings_and_ints.rb:4:in `<main>'
错误的隐式转换整数到字符串的意思是,Ruby只能将一个字符串连接到现有字符串中。
Note
strings_and_ints.rb:4:in `+’: no implicit conversion of Fixnum into String (TypeError)
from strings_and_ints.rb:4:in `
在以前的Ruby版本中,关键字Fixnum被赋予给整数的数据类型。它是Fixed Number的简称。在Ruby 2.4中,Fixnum及其对应的Bignum不再存在,而是被Integer替代。
我们可以改变我们的程序,并将数字27放在引号中(”27″),这样它就被声明为字符串而不是整数。或者我们可以在创建字符串时将数字转换为字符串,就像这样:
my_name = "Sammy the Shark"
my_number = 27
print my_name + my_number.to_s
.to_s方法将整数转换为字符串。这是一个更好的方法,因为它使我们可以在程序中保持数字的整体。我们只需要在打印时将其作为字符串,但如果我们需要在程序的其他部分逻辑中使用它作为整数,可能希望它是一个整数。
再次运行程序,你将在屏幕上看到 Sammy the Shark27 的输出。
当涉及到邮政编码、货币、电话号码以及其他你想要在屏幕上与文本一起显示的数字数据时,经常会遇到将数字转化为字符串进行连接的情况。
连接是强大的,但也很棘手。如果你不小心漏掉一个+操作符,就会出现语法错误。而且如果你需要将字符串与保存数字的变量连接起来,你还需要将变量转换为字符串。Ruby提供了另一种将变量值插入字符串的方式,称为字符串插值,它解决了这两个问题。
使用字符串插值
当连接字符串和变量时,输出可能很难阅读和调试。字符串插值解决了这个问题,它允许您在双引号中嵌入表达式的字符串中。
不要写这个,
"My name is " + my_name + "!"
你可以做这个。
"My name is #{my_name}!"
不使用终止字符串和加号操作符,而是使用 #{} 语法将变量括起来。这种语法告诉 Ruby 对表达式进行求值,并将其注入到字符串中。
试一试。创建一个名为interpolation.rb的新程序,并添加以下代码:
my_name = "Sammy the Shark"
my_age = "none of your business"
output = "My name is #{my_name} and my age is #{my_age}."
puts output
这是你之前写过的同一个程序,但这次我们会使用字符串插值来创建输出。
字符串插值还有一个好处:它可以自动将数值转换为字符串。还记得你的strings_and_integers.rb程序吗?再次打开你的编辑器并将最后一行改成如下形式:
my_name = "Sammy the Shark"
my_number = 27
# use interpolation instead of concatenation
print "My name is #{my_name} and my favorite number is #{my_number}."
当你运行程序时,Ruby将会自动将my_number转换成字符串,并且你的程序将会打印出以下输出。
OutputMy name is Sammy the Shark and my favorite number is 27.
字符串插值非常强大且方便。它也是与变量连接字符串的首选方法。
字符串字面值和字符串值
请注意,您在代码中创建的所有字符串都包含在引号中,但实际输出的结果不包含引号。
在提及每个时,它们之间有区别。字符串文字是在源代码中所写的字符串,包括引号。字符串值是您在输出中看到的内容,不包含引号。
这是一个字符串字面值。
"Sammy the Shark"
字符串的值将是鲨鱼山姆 (The string value would be Sammy the Shark.)
大多数情况下,您不必担心这个区别,除非您想在字符串中使用特殊字符,例如引号或撇号。
在字符串中转义引号和撇号
由于引号用于表示字符串,如果你想在字符串中使用撇号和引号,你需要额外的努力。
如果你在单引号字符串的中间尝试使用撇号,像这样:
'This isn't what I wanted.'
在这个例子中,可以从奇怪的高亮显示中看出,中文的”不”字结尾的字符串中的英文撇号没有结束字符串。因此,Ruby解释器将尝试解析剩下的意图字符串,而你将会得到一个错误。
如果你在一个被双引号包围的字符串中使用双引号,你会遇到相同的情况。
"Sammy says, "Hello!""
在这个例子中,Hello前面的右双引号终止了字符串,并且Hello!之后的双引号创建了一个新的字符串,它没有匹配的右双引号来终止它,因此Ruby将显示一个错误。
为了避免这个问题,你有几个选项。首先,你可以使用替代语法来创建字符串;如果你必须在字符串中使用双引号,那么用单引号来定义字符串,反之亦然。你也可以对引号进行转义,或者使用不同的Ruby语法来定义字符串。让我们来看看每种方法。
选项1:使用备用字符串语法。
解决这些问题最简单的方法是:当你的字符串里面需要包含双引号时,用单引号将字符串括起来;当你的字符串需要使用单引号时,用双引号将字符串括起来。
不要使用单引号定义这个字符串:
'This isn't what I wanted.'
用双引号来定义它。
"This isn't what I wanted."
相反,不使用双引号来定义这个字符串。
"Sammy says, "Hello!""
请使用单引号:
'Sammy says, "Hello!"'
使用的备选语法可以解决一些紧急困境,但并不总是适用。例如,这个字符串既不能通过任何一种方法解决。
"Sammy says, "I'm a happy shark!""
在这个例子中,前面的结尾双引号”在I’m之前导致了混乱。它终止了第一个字符串,然后Ruby遇到了I’m中的撇号,这将开始一个新的值为”我是一只开心的鲨鱼!””的字符串。但是这个新的字符串没有匹配的单引号来终止它。而使用单引号来包含字符串引入了一个类似的问题:
'Sammy says, "I'm a happy shark!"'
这次”I’m”中的撇号终结了这个字符串。
使用替代语法也会使您的代码不一致。在字符串语法之间不断切换可能会令人困惑,我们可以使用转义字符来解决这个问题。
选项2:字符串中的转义字符的转换
反斜杠字符(\),通常在字符串中被称为转义字符,可以防止Ruby直接解释字符串中的下一个字符。
这是我们有问题的字符串,使用双引号进行编码,并且嵌套了双引号。
"Sammy says, "I'm a happy shark!""
创建一个名为quoting.rb的新的Ruby程序,并将以下代码添加到文件中。
print "Sammy says, "I'm a happy shark!""
运行程序。
- ruby quoting.rb
然后你会看到这个结果。
Outputquoting.rb:1: syntax error, unexpected tCONSTANT, expecting end-of-input
print "Sammy says, "I'm a happy shark!""
^
为了修复错误,需要在内部双引号前使用反斜杠。
print "Sammy says, \"I'm a happy shark!\""
然后再次运行程序,你会看到你预期的输出结果。
Sammy says, "I'm a happy shark!"
请注意,在这个例子中你不必转义撇号,因为没有冲突。你只需要转义那些会让Ruby混淆的引号。
你可以通过使用不同的语法来定义字符串来完全避免转义引号。
选项3:使用字符串的替代语法。
到目前为止,您使用引号来定义字符串的边界。您也可以使用其他字符来创建Ruby中的字符串。您可以通过在百分号后指定它来定义定界符或包围字符串的字符,就像这样:
%$Sammy says, "I'm a happy shark!"$
这个语法会自动为您转义嵌入的字符串。实际的字符串看起来像这样:
"Sammy says, \"I'm a happy shark!\""
然而,改变分隔符意味着如果需要使用它,你就必须对分隔符进行转义。在这种情况下,如果你必须在字符串中使用美元符号,你需要转义字符串中的字面美元符号。
为了避免这种情况,你也可以使用一对大括号、方括号或者圆括号作为分隔符。大括号是最常见的。
%{Sammy says, "I'm a happy shark!"}
如果你需要的话,所有这些格式都支持字符串插值。
droplets = 5
print %{Sammy says, "I just created #{droplets} droplets!"}
在Ruby程序中,你还会见到%Q{}和%q{}用来定义字符串。%Q{}语法与双引号字符串的用法完全相同,这意味着你不必转义双引号,同时可以使用字符串插值。
droplets = 5
print %Q{Sammy says, "I just created #{droplets} droplets!"}
%q{}语法与单引号字符串完全相同。
or
%q{}语法与单引号字符串一模一样的。
%q{Sammy says, "I'm a happy shark!"}
在某些程序中,你可能会看到使用括号或方括号的%q和%Q语法,而不是花括号。
正如你所看到的,在Ruby中创建字符串的方法有很多种。无论你选择哪一种方法,在你的代码中要保持一致。你会发现%Q{}和%{}方法最常见。
既然你已经知道如何处理特殊字符了,那我们来看看如何处理长字符串和换行字符。
长字符串和换行
有时候你可能想在字符串中插入换行符或回车符。你可以使用“\n”或“\r”转义字符在代码中插入换行。
output = "This is\na string\nwith newlines"
puts output
这个程序会产生这个输出。
OutputThis is
a string
with newlines
这个方法在技术上可以实现我们在多行输出。然而,将一个非常长的字符串写在一行上会使其很难阅读和处理。有几种解决方案。
首先,你可以使用连接运算符将字符串分成多行。
output = "This is a\n" +
"longer string\n" +
"with newlines."
puts output
这个只是将三个字符串连接起来,类似于你已经做过的。
您也可以直接在字符串中加入换行符:
output = "This is a
longer string
with newlines"
puts output
你也可以使用任意的其他字符串语法来创建多行字符串。
output = %{This is a
longer string
with newlines}
puts output
在这两个例子中,注意到我们不需要换行符(\n)字符。这种方法保留了空格,包括缩进和换行符。
因此,输出将包含换行符以及所有前导的缩进,例如:
OutputThis is a
longer string
with newlines
为了防止这种情况发生,从你的代码中去除多余的空格。
output = %{This is a
longer string
with newlines
}
您还可以使用heredoc(在程序中用于多行字符串文字的术语)来创建多行字符串。以下是如何编写此代码的方法:
output = <<-END
This is a
longer string
with newlines
END
“<<"和"<<"标记表示heredoc的开始和结束。
Ruby的Heredocs还可以保留空格字符,这意味着如果你在Heredoc中缩进代码,前导缩进也会被保留。因此,以下代码:
output = <<-END
This is a
longer string
with newlines
END
将以两个空格缩进的方式打印出来。
Ruby 2.3及更高版本提供了“波浪长字符串”语法,可以自动删除前导空白。将波浪线“-”替换为波浪号“~”,所以<<-变为<<~,像这样:
output = <<~END
This is a
longer string
with newlines
and the code is indented
but the output is not.
END
这会产生以下输出:
OutputThis is a
longer string
with newlines
and the code is indented
but the output is not.
这样可以让你使用纯文本本文并保持代码整齐缩进。
在Ruby中,Heredocs也支持字符串插值。
正如你所见,Ruby中有很多处理换行和多行字符串的方法。在与现有的Ruby代码一起工作时,你会遇到所有这些方法,因为每个项目都倾向于有自己的风格。在你自己的代码中,选择适合你的风格并保持一致。
字符串复制
有时候你可能需要使用 Ruby 来多次重复一个字符序列。你可以使用 * 操作符来实现。和 + 操作符一样,* 操作符在和数字一起使用时有不同的用途,它是乘法运算符。当和一个字符串和一个整数一起使用时,* 是字符串复制运算符,可以使用提供的整数来重复一个字符串多少次。
要打印九次Sammy,您需要使用以下代码:
print "Sammy" * 9
这段代码的输出结果如下:
OutputSammySammySammySammySammySammySammySammySammy
你可以使用这个来创建一些漂亮的ASCII艺术。创建一个名为banner.rb的文件,并添加以下代码。
puts "=" * 15
puts "| Hello World |"
puts "=" * 15
你在运行程序之前能想象它会产生什么吗?
它产生了这个输出。
Output===============
| Hello World |
===============
这只是一个小例子,展示了如何让电脑为您执行重复任务。
结论
在这个教程中,你学习了如何在Ruby编程语言中处理字符串数据类型。你创建了新的字符串,将其与其他字符串连接起来,并处理了换行符、引号和撇号。然后,你使用了字符串插值来更轻松地混合字符串和变量值,并学习了如何重复字符串。