如何在Ruby中处理字符串

介绍

A string is a sequence of one or more characters that may consist of letters, numbers, or symbols.

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方法会按照字符串的原样显示。

试一试。创建一个新的Ruby程序,命名为print.rb,使用你的文本编辑器,并使用print方法打印三个字符串:

print.rb
print 'This is the first string.'
print 'This is the second string.'
print 'This is the third string.'

保存文件并运行程序:

  1. ruby print.rb

你会看到以下输出:

Output
This is the first string.This is the second string.This is the third string.

而不是三个字符串各自占据一行,所有三个字符串都打印在一行上。print方法将字符串打印到屏幕上,但如果你希望每个字符串占据一行,就必须自己添加换行符。

如果你想让所有三个字符串分别占据一行,请改用puts方法。修改你的程序,使用puts而不是print

print.rb
puts 'This is the first string.'
puts 'This is the second string.'
puts 'This is the third string.'

现在再次运行程序,你将看到这个输出:

Output
This 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

  1. nano string_variables.rb

然后添加以下代码:

string_variables.rb
my_name = "Sammy the Shark"
my_age = "none of your business"

puts my_name
puts my_age

这个程序定义了两个变量:my_namemy_age。每个变量都被分配了一个字符串。我们然后使用puts方法来分别在各自的行上打印出每个字符串。

使用CTRL + Xy保存文件,然后执行程序:

  1. ruby string_variables.rb

你会看到以下输出:

Output
Sammy the Shark none of your business

通过将字符串分配给变量,你可以避免每次想要使用它时重复输入同一个字符串,这使得在程序中处理和操作字符串变得更加容易。

让我们看看如何将字符串连接在一起以创建新的字符串。

字符串连接

连接意味着将两个或更多字符串连接在一起,以创建一个新的字符串。为了进行连接,我们使用连接运算符,由+符号表示。当与算术运算一起使用时,+符号也是加法运算符。

以下是如何连接字符串sammyshark的示例:

"sammy" + "shark"

这将产生以下输出:

Output
sammyshark

连接将字符串端对端地连接起来,将它们组合在一起并输出一个全新的字符串值。如果你想在单词sammyshark之间有一个空格,你必须在其中一个字符串中包含该空格,像这样:

"sammy " + "shark"

现在,在程序中你可能不会真的这样编写代码,但你经常需要将字符串和变量混合在一起,这就是连接的用武之地。

以下是一个例子:

color = "Blue"
print "My favorite color is " + color

这将导致输出My favorite color is blue。请注意,在字符串中单词is后面留了一个空格,这样输出中字符串和变量值之间就会有一个空格。

你可以通过这种方式将多个字符串连接在一起。创建文件concatenation.rb并添加以下代码:

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_namemy_age,每个都有其自己分配的字符串,就像之前做过的一样。但这一次,我们不是打印这些值,而是打印一个使用连接来打印这些值的字符串,并带有一些上下文信息。

当你运行这个程序时,你将看到以下输出:

Output
My name is Sammy the Shark and my age is none of your business.

在这个小程序中,你使用了连接运算符将变量插入到字符串中。

当你通过连接运算符将两个或更多字符串组合在一起时,你创建了一个新的字符串,可以在整个程序中使用,所以你可能希望将你创建的字符串分配给一个新的变量,稍后可以使用:

concatenation.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

在像这样的小程序中,使用额外的 output 变量可能是不必要的。但在更大的程序中,你可能希望使用连接来创建一个字符串,你将在多个地方使用它。将数据处理(如连接和算术)与输出分开是一个好习惯,因为最终你的程序会变得更大,你会希望将逻辑和输出分开成单独的文件或组件,以便更容易管理。

确保不要在两种不同的数据类型之间使用 + 运算符。例如,你不能将字符串和整数连接在一起。

要查看会发生什么,创建一个名为 strings_and_integers.rb 的新程序,内容如下:

strings_and_integers.rb
my_name = "Sammy the Shark"
my_number = 27

print my_name + my_number

这次我们有一个名为 my_name 的变量,其中包含字符串 Sammy the Shark,还有一个名为 my_number 的变量,其中包含整数 27。我们知道 27 不是字符串,因为它没有被引号包围。它也没有小数点,所以我们知道它是一个整数。

如果你运行程序:

  1. ruby strings_and_ints.rb

你会看到这个错误消息:

Output
strings_and_ints.rb:4:in `+': no implicit conversion of Integer into String (TypeError) from strings_and_ints.rb:4:in `<main>'

错误no implicit conversion of Integer into String表示Ruby只能将字符串连接到现有字符串上。

在Ruby 2.3及以下版本中,您会看到这个错误消息:

strings_and_ints.rb:4:in `+': no implicit conversion of Fixnum into String (TypeError)
from strings_and_ints.rb:4:in `<main>'

关键字Fixnum是以前版本Ruby中整数的数据类型。它是Fixed Number的简称。在Ruby 2.4中,Fixnum及其对应的Bignum不再存在,而是被Integer替代。

我们可以修改我们的程序,将数字27放在引号中("27"),这样它就被声明为字符串而不是整数。或者我们可以在创建字符串时将数字转换为字符串,就像这样:

strings_and_integers.rb
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的新程序,并添加以下代码:

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程序吗?再次在编辑器中打开该文件,但将最后一行更改为如下所示:

strings_and_integers.rb
my_name = "Sammy the Shark"
my_number = 27

# 使用插值而不是拼接
print "My name is #{my_name} and my favorite number is #{my_number}."

Ruby 将自动将 my_number 转换为字符串,当您运行它时,您的程序将打印以下输出:

Output
My name is Sammy the Shark and my favorite number is 27.

字符串插值功能强大且方便。这也是与变量拼接字符串的首选方法。

字符串文字和字符串值

请注意,您创建的所有字符串都在代码中用引号括起来,但实际打印的输出不包括引号。

在引用它们时有一个区别。字符串文字是在源代码中编写的字符串,包括引号。字符串值是您在输出中看到的内容,不包括引号。

这是一个字符串文字:

"Sammy the Shark"

字符串值将是 Sammy the Shark

在大多数情况下,您不必担心这种区别,除非您想在字符串中使用引号或撇号等特殊字符。

在字符串中转义引号和撇号

由于引号用于表示字符串,如果要在字符串中使用撇号和引号,则需要额外的工作。

如果您尝试在单引号字符串中间使用撇号,就像这样:

'This isn't what I wanted.'

则代码中的isn't中的撇号将结束字符串,正如您在此示例中看到的奇怪突出的部分一样。因此,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 中的撇号,从而开始一个新字符串,其值为 m a happy shark!""。但是这个新字符串没有匹配的单引号来终止它。而使用单引号来括起字符串也会引入类似的问题:

'Sammy says, "I'm a happy shark!"'

这次 I'm 中的撇号终止了字符串。

使用备选语法还会使您的代码不一致。不断地在字符串语法之间切换会让人感到困惑,我们可以使用转义字符来解决这个问题。

选项 2:在字符串中转义字符

字符反斜杠(\),通常在字符串中被称为转义字符,将阻止Ruby直接解释字符串中的下一个字符。

这是我们有问题的字符串,以双引号编码,并包含双引号:

"Sammy says, "I'm a happy shark!""

创建一个名为quoting.rb的新Ruby程序,并将此代码添加到文件中:

quoting.rb
print "Sammy says, "I'm a happy shark!""

运行程序:

  1. ruby quoting.rb

然后你会看到这个输出:

Output
quoting.rb:1: syntax error, unexpected tCONSTANT, expecting end-of-input print "Sammy says, "I'm a happy shark!"" ^

为了修复错误,在内部双引号前使用反斜杠:

quoting.rb
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!"}

您还会看到%Q{}%q{}用于在Ruby程序中定义字符串。%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

该程序将生成以下输出:

Output
This 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)。这种方法保留空格,包括缩进和换行。

因此,输出将包含换行符以及所有前导缩进,如下:

Output
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

<<-ENDEND标记表示heredoc的开始和结束。

在Ruby中,Heredocs还保留空白字符,这意味着如果在heredoc中缩进代码,则前导缩进也会被保留。因此,这段代码:

output = <<-END
This is a
longer string
with newlines
END

会以两个空格的缩进打印出来。

Ruby 2.3及更高版本提供了“squiggly heredoc”语法,自动删除此前导空格。将heredoc定义中的连字符替换为波浪线,因此<<-变成<<~,如下所示:

output = <<~END
This is a
longer string
with newlines
and the code is indented
but the output is not.
END

这会产生以下输出:

Output
This is a longer string with newlines and the code is indented but the output is not.

这样可以使用heredocs并保持代码缩进得很好。

Ruby中的Heredocs还支持字符串内插。

正如你所看到的,Ruby中有很多处理换行和多行字符串的方法。在处理现有Ruby代码时,你会遇到所有这些方法,因为每个项目往往都有自己的风格。在你自己的代码中,选择适合你的风格并保持一致。

字符串复制

有时你可能需要使用Ruby来重复多次一个字符字符串。你可以使用*运算符来实现。与+运算符不同,当与数字一起使用时,*运算符具有不同的用途,其中它是乘法的运算符。当与一个字符串和一个整数一起使用时,*字符串复制运算符,使用你提供的整数重复单个字符串。

为了打印出 Sammy 九次,您可以使用以下代码:

print "Sammy" * 9

此代码产生以下输出:

Output
SammySammySammySammySammySammySammySammySammy

您可以利用这个功能创建一些漂亮的ASCII艺术。创建一个名为 banner.rb 的文件,并添加以下代码:

puts "=" * 15
puts "| Hello World |"
puts "=" * 15

在运行程序之前,您能想象出这个程序会产生什么样的结果吗?

它产生以下输出:

Output
=============== | Hello World | ===============

这只是如何让计算机为您执行重复任务的一个小例子。

结论

在本教程中,您学会了如何处理 Ruby 编程语言中的字符串数据类型。您创建了新的字符串,将它们与其他字符串连接,并处理了换行符、引号和撇号。然后,您使用了字符串插值,使混合字符串和变量值变得更容易,还学会了如何重复字符串。

Source:
https://www.digitalocean.com/community/tutorials/how-to-work-with-strings-in-ruby