Ruby字符串处理:从基础到高级技巧全解析
引言
字符串是由一个或多个字符组成的序列,这些字符可以是字母、数字或符号。
在Ruby中,字符串是对象。与许多其他语言不同的是,Ruby中的字符串是可变的,这意味着它们可以在原地被修改,而无需创建新的字符串实例。
在您编写的几乎每个程序中都会用到字符串。字符串可以用于显示信息并与用户进行文本通信。实际上,您正在阅读的这个页面就是由通过网络浏览器在您的屏幕上显示的字符串构成的。字符串是编程中最基础且最重要的概念之一。
在本教程中,您将学习如何在Ruby中处理字符串。您将创建字符串,将其显示在屏幕上,将其存储在变量中,将多个字符串连接在一起,还将学习如何处理特殊字符,如换行符、撇号和双引号。
创建并打印字符串
在Ruby中,字符串可以存在于单引号 '
或双引号 "
中。因此,要创建一个字符串,只需将一系列字符包裹在其中之一中。
'这是一个用单引号表示的字符串。'
"这是一个用双引号表示的字符串。"
您可以选择使用单引号或双引号。在大多数情况下,您选择哪种方式并不重要,只要保持一致即可。然而,使用双引号允许您进行字符串插值,这是您将在本教程后续部分学习的内容。
要在程序中显示一个字符串,您可以使用 print
方法。
print "让我们打印出这个字符串。"
print
方法会按照原样显示字符串。
试一试。在您的文本编辑器中创建一个名为 print.rb
的新Ruby程序,并使用 print
方法打印三个字符串。
print '这是第一个字符串。'
print '这是第二个字符串。'
print '这是第三个字符串。'
保存文件并运行程序。
- ruby print.rb
您会看到以下的输出:
输出这是第一个字符串。这是第二个字符串。这是第三个字符串。
不是将三个字符串分别打印到各自的行上,而是将这三个字符串一起打印到同一行上。print
方法会将字符串输出到屏幕上,但是如果您想让每个字符串显示在独立的行上,就需要自己添加换行符。
如果您想让这三个字符串分别显示在不同行上,请使用 puts
方法。修改您的程序,用 puts
代替 print
。
puts '这是第一个字符串。'
puts '这是第二个字符串。'
puts '这是第三个字符串。'
现在再次运行程序,就会看到以下输出结果。
输出这是第一个字符串。
这是第二个字符串。
这是第三个字符串。
puts
方法打印您指定的字符串,同时会自动在字符串的末尾添加换行符。
将字符串存储到变量中
变量是计算机内存中一个命名的引用位置。您可以使用变量来存储数据并在以后检索它。
要存储一个字符串到变量中,需要定义变量名并赋予字符串的值。
my_string = '这是我的字符串'
然后,要检索值,请使用变量的名称。
print my_string
要自己测试,请在您的编辑器中使用以下命令创建名为 string_variables.rb
的文件。
- nano string_variables.rb
然后添加以下代码:
my_name = "鲨鱼萨米"
my_age = "无可奉告"
puts my_name
puts my_age
这个程序定义了两个变量:my_name
和 my_age
。每个变量都被赋予了一个字符串。然后,我们使用 puts
方法将每个字符串分别打印在自己的一行上。
使用 Ctrl + X
和 Y
保存文件,然后执行程序。
- ruby string_variables.rb
您将看到以下输出:
输出鲨鱼萨米
无可奉告
通过给变量赋值字符串,您可以避免每次使用字符串时都要重复输入相同的字符串,从而更轻松地处理和操作程序中的字符串。
让我们来看看如何将字符串连接在一起创建新的字符串。
字符串连接 (String Concatenation)
连接意味着将两个或多个字符串连接在一起以创建一个新的字符串。为了进行连接,我们使用连接运算符,表示为加号(+
)符号。当用于算术运算时,加号符号也是加法运算符。
这是如何将字符串“sammy”和“shark”连接在一起:
"sammy" + "shark"
这将产生以下的输出结果。
输出sammyshark
连接将字符串拼接在一起,将它们合并并输出一个全新的字符串值。如果您想在单词“sammy”和“shark”之间添加空格,您需要在其中一个字符串中包含该空格,像这样:
"sammy " + "shark"
现在,在程序中您不会真的像这样写代码,但您经常需要将字符串和变量混合在一起,这就是拼接的用武之地。
这里举个例子:
color = "蓝色"
print "我最喜欢的颜色是 " + color
这将导致输出为“我最喜欢的颜色是 蓝色”。请注意,在字符串中的单词“是”后面留有一个空格,这样输出中字符串和变量值之间就会有一个空格。
你可以通过这种方法将多个字符串连接在一起。创建文件 concatenation.rb
,并添加以下代码:
这是文章《如何在Ruby中处理字符串》的第2部分(共5部分)。
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
,每个变量都包含一个字符串,就像您之前操作的那样。但这一次,我们不是直接打印变量的值,而是通过字符串连接(Concatenation)将这些值与一些上下文信息一起打印出来。
当您运行此程序时,您会看到以下输出结果:
输出My name is Sammy the Shark and my age is none of your business.
在这个小程序中,您使用了字符串连接将变量插入到字符串中。
当您通过连接将两个或多个字符串组合时,您正在创建一个新的字符串,您可以在整个程序中使用它。因此,您可能希望将创建的字符串分配给一个新的变量,以便将来使用。
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
在像这样的小程序中,使用额外的输出变量可能不是必需的。但在较大的程序中,您可能希望使用连接创建一个字符串,并在多个地方使用该字符串。此外,将数据处理(如连接和算术运算)与输出分离是一个好习惯,因为随着程序的扩展,您可能希望将逻辑和输出分离到不同的文件或组件中,以便于管理。
请确保不要在两种不同的数据类型之间使用 +
运算符。例如,您不能将字符串和整数连接在一起。
为了了解会发生什么,创建一个名为 字符串与整数.rb
的新程序,内容如下:
my_name = "Sammy the Shark"
my_number = 27
print my_name + my_number
这次我们有一个变量 my_name
,它存储了字符串 “Sammy the Shark”,还有一个变量 my_number
,它存储了整数 27。我们知道 27 不是一个字符串,因为它没有被引号包围。它也没有小数点,所以我们知道它是一个整数。
如果您运行这个程序:
- ruby 字符串与整数.rb
您会看到这个错误信息:
输出字符串与整数.rb:4:in `+': no implicit conversion of Integer into String (TypeError)
from 字符串与整数.rb:4:in `<main>'
“错误的隐式转换整数到字符串”的意思是,Ruby 只能将一个字符串连接到现有字符串中。
注意
在 Ruby 版本 2.3 及以下,您会看到以下错误信息:
字符串与整数.rb:4:in `+': no implicit conversion of Fixnum into String (TypeError)
from 字符串与整数.rb:4:in `<main>'
在以前的 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 + "!"
您可以这样做:
这是文章《如何在Ruby中处理字符串》的第3部分(共5部分)。
"我的名字是 #{my_name}!"
不使用终止字符串和加号操作符,而是使用 #{}
语法将变量括起来。这种语法告诉 Ruby 对表达式进行求值,并将其注入到字符串中。
试一试。创建一个名为 interpolation.rb
的新程序,并添加以下代码:
.rb
文件中进行插值。my_name = "Sammy the Shark"
my_age = "无可奉告"
output = "我的名字是 #{my_name},我的年龄是 #{my_age}。"
puts output
这是你之前写过的同一个程序,但这次我们会使用字符串插值来创建输出。
字符串插值还有一个好处:它可以自动将数值转换为字符串。还记得你的 strings_and_integers.rb
程序吗?再次打开你的编辑器并将最后一行改成如下形式:
my_name = "Sammy the Shark"
my_number = 27
# 使用插值而非连接
print "我的名字是 #{my_name},我最喜欢的数字是 #{my_number}。"
当你运行程序时,Ruby 将会自动将 my_number
转换成字符串,并且你的程序将会打印出以下输出。
输出我的名字是 Sammy the Shark,我最喜欢的数字是 27。
字符串插值非常强大且方便。它也是与变量连接字符串的首选方法。
字符串字面量和字符串值
请注意,您在代码中创建的所有字符串都包含在引号中,但实际输出的结果不包含引号。
在提及每个时,它们之间有区别。字符串字面量是在源代码中所写的字符串,包括引号。字符串值是您在输出中看到的内容,不包含引号。
这是一个字符串字面量。
"Sammy the Shark"
字符串的值将是 Sammy the Shark。
大多数情况下,您不必担心这个区别,除非您想在字符串中使用特殊字符,例如引号或撇号。
在字符串中转义引号和撇号
由于引号用于表示字符串,如果你想在字符串中使用撇号和引号,你需要额外的努力。
如果你在单引号字符串的中间尝试使用撇号,像这样:
'这不是我想要的。'
在这个例子中,可以从奇怪的高亮显示中看出,字符串中的英文撇号 '
没有结束字符串。因此,Ruby 解释器将尝试解析剩下的意图字符串,而你将会得到一个错误。
如果你在一个被双引号包围的字符串中使用双引号,你会遇到相同的情况。
"Sammy 说,"你好!""
在这个例子中,Hello
前面的右双引号终止了字符串,并且 Hello!
之后的双引号创建了一个新的字符串,它没有匹配的右双引号来终止它,因此 Ruby 将显示一个错误。
为了避免这个问题,你有几个选项。首先,你可以使用替代语法来创建字符串;如果你必须在字符串中使用双引号,那么用单引号来定义字符串,反之亦然。你也可以对引号进行转义,或者使用不同的 Ruby 语法来定义字符串。让我们来看看每种方法。
选项1:使用备用字符串语法。
解决这些问题最简单的方法是:当你的字符串里面需要包含双引号时,用单引号将字符串括起来;当你的字符串需要使用单引号时,用双引号将字符串括起来。
不要使用单引号定义这个字符串:
'这不是我想要的。'
用双引号来定义它。
"这不是我想要的。"
相反,不要使用双引号来定义这个字符串。
"Sammy 说,"你好!""
请使用单引号:
'Sammy 说,“你好!”'
使用的备选语法可以解决一些紧急困境,但并不总是适用。例如,这个字符串既不能通过任何一种方法解决。
这是文章《如何在Ruby中处理字符串》的第4部分(共5部分)。
"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{}
语法与单引号字符串一模一样。
%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
这个方法在技术上可以实现我们在多行输出。然而,将一个非常长的字符串写在一行上会使其很难阅读和处理。有几种解决方案。
首先,你可以使用连接运算符将字符串分成多行。
这是文章《如何在Ruby中处理字符串》的第5部分(共5部分)。
内容片段:
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
)字符。这种方法会保留空格,包括缩进和换行符。
因此,输出将包含换行符以及所有前导的缩进,例如:
输出This 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
<<-END
和 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
这会产生以下输出:
输出This 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
这段代码的输出结果如下:
输出SammySammySammySammySammySammySammySammySammy
你可以使用这个来创建一些漂亮的ASCII艺术。创建一个名为banner.rb
的文件,并添加以下代码。
puts "=" * 15
puts "| Hello World |"
puts "=" * 15
你在运行程序之前能想象它会产生什么吗?
它产生了以下输出。
输出===============
| Hello World |
===============
这只是一个简单示例,展示了如何让计算机为您执行重复任务。
结论
在这个教程中,你学习了如何在Ruby编程语言中处理字符串数据类型。你创建了新的字符串,将其与其他字符串连接起来,并处理了换行符、引号和撇号。然后,你使用了字符串插值来更轻松地混合字符串和变量值,并学习了如何重复字符串。