Ruby 字符串
Ruby 字符串
Section titled “Ruby 字符串”Ruby 中的 String 对象用于存储和操作字符序列。在底层,这些字符根据字符串的编码(在现代 Ruby 中通常是 UTF-8)以字节表示。
字符串字面量可以使用单引号(')或双引号(`”“)创建。
单引号字符串执行最小化处理。大多数转义序列(如 \n)不会被解释,也不支持表达式插值。
'This is a simple Ruby string literal. \n is not a newline here.'如果您需要在单引号字符串中包含撇号,请在其前面加上反斜杠:
'Won\'t you read O\'Reilly\'s book?'双引号字符串支持各种转义序列和表达式插值。
"This string supports interpolation: #{1 + 1} and escape sequences like newlines \n and tabs \t."在两种类型的引号中,反斜杠也可以转义另一个反斜杠,因此 \\ 会变成一个反斜杠字符。
您也可以使用 String.new 创建字符串:
empty_string = String.newgreeting = String.new("Hello")考虑在 Ruby 文件的顶部使用 # frozen_string_literal: true 指示。这个指示(pragma)默认冻结文件中的所有字符串字面量,这可以提升性能并防止意外修改。
# frozen_string_literal: true
my_string = "hello"# my_string << " world" # 这将引发一个 FrozenError表达式替换 (插值)
Section titled “表达式替换 (插值)”表达式替换允许使用 #{ 和 } 将任何 Ruby 表达式的值嵌入到双引号字符串(或其他支持插值的上下文,如 %Q{})中:
#!/usr/bin/env ruby# frozen_string_literal: true
x, y, z = 12, 36, 72puts "The value of x is #{x}."puts "The sum of x and y is #{x + y}."puts "The average was #{(x + y + z) / 3}."这将产生以下结果:
The value of x is 12.The sum of x and y is 48.The average was 40.通用定界字符串
Section titled “通用定界字符串”Ruby 提供了百分号字符串语法(%),用于使用任意定界符创建具有不同行为的字符串。常见的形式包括:
%q{...}或%q(...)或%q[...]等: 非插值字符串 (类似于单引号)。定界符可以是任意匹配的非字母数字字符对或成对匹配的字符,如(),[],{},<>。%Q{...}或%{...}: 插值字符串 (类似于双引号)。%x{...}: 插值字符串,会作为 shell 命令执行,并返回其标准输出 (类似于反引号 “)。%w{word1 word2}: 由单词组成的非插值数组,按空白字符分割。%W{word1 #{expr} word2}: 由单词组成的插值数组,按空白字符分割。
# Equivalent to "Ruby is fun."str1 = %Q{Ruby is fun.}
# Equivalent to 'Ruby is fun.'str2 = %q[Ruby is fun.]
# Equivalent to `ls -l` (executes command)# output = %x(ls -l)
# Example with different delimitersputs %q(Don't need to escape apostrophes here.)puts %Q[Interpolation works: #{2 * 3}]下表列出了常见的转义序列。它们在双引号字符串和类似上下文(例如 %Q{})中被解释。在单引号字符串中,只有 \' 和 \\ 具有特殊含义。
| 表示法 | 描述 |
|---|---|
| \ | 反斜杠 |
| ’ | 单引号 |
| ” | 双引号 |
| \a | 响铃或警报 (0x07) |
| \b | 退格符 (0x08) |
| \e | 转义符 (0x1b) |
| \f | 换页符 (0x0c) |
| \n | 换行符 (0x0a) |
| \r | 回车符 (0x0d) |
| \s | 空格符 (0x20) |
| \t | 制表符 (0x09) |
| \v | 垂直制表符 (0x0b) |
| \nnn | 八进制表示法 (n 是 0-7) |
| \xnn | 十六进制表示法 (n 是 0-9, a-f, A-F) |
| \unnnn | Unicode 字符 (nnnn 是十六进制) |
| \u{nnnn …} | Unicode 字符 (一个或多个十六进制编码) |
现代 Ruby(1.9 及更高版本)对字符编码具有强大的支持。字符串感知编码(encoding-aware),并且 UTF-8 是 Ruby 应用程序中最常用和推荐的编码。
默认编码设置:
Section titled “默认编码设置:”Ruby 管理着几个默认编码设置:
Encoding.default_external: 指定从外部来源(例如文件、网络套接字)创建的字符串的默认编码。它通常根据您的系统 locale 设置(例如,LANG环境变量,在现代系统上通常是 UTF-8)。Encoding.default_internal: 如果设置,从外部来源读取的字符串将自动从default_external转码到此default_internal编码。除非特定内部处理需要不同的编码,否则通常将其保留为nil。- 脚本编码: 您的 Ruby 源文件本身的编码。您应该在文件的顶部使用“魔法注释”来指定此编码,特别是当您的源代码在字符串字面量或注释中包含非 ASCII 字符时:
# encoding: utf-8
# Your Ruby code here...# Or, more commonly combined with frozen string literal pragma:# frozen_string_literal: true# encoding: utf-8
MY_CONSTANT = "你好世界" # 中文的 Hello world如果没有这个魔法注释,Ruby 可能会假定不同的编码(例如在没有 UTF-8 BOM 的情况下假定 US-ASCII),从而可能误解字符串字面量。UTF-8 是普遍推荐的脚本编码。
您可以使用 my_string.encoding 检查字符串的编码。要将字符串转换为其他编码,使用 my_string.encode('Target-Encoding') 或 my_string.encode(Encoding::TARGET_ENCODING)。如果您知道某个字符串的字节序列代表的编码与 Ruby 假定的不同,您可以使用 my_string.force_encoding('Correct-Encoding')。
#!/usr/bin/env ruby# encoding: utf-8
s = "hello résumé"puts "Original string: '#{s}', Encoding: #{s.encoding}"
begin s_latin1 = s.encode(Encoding::ISO_8859_1) puts "Encoded to Latin1: '#{s_latin1}', Encoding: #{s_latin1.encoding}"rescue Encoding::UndefinedConversionError => e puts "Error encoding to Latin1: #{e.message}" # 如果 s 包含 ISO-8859-1 中无法表示的字符,则可能发生这种情况end
# force_encoding 的示例 (谨慎使用)byte_sequence = "\xC3\xA9".b # 'é' 的一个 UTF-8 序列,.b 使其变为 ASCII-8BITputs "Byte sequence: #{byte_sequence.inspect}, Encoding: #{byte_sequence.encoding}"
utf8_char = byte_sequence.force_encoding(Encoding::UTF_8)puts "Forced to UTF-8: '#{utf8_char}', Encoding: #{utf8_char.encoding}"
# 在旧版本 Ruby (1.9 之前) 中使用的 $KCODE 变量已废弃且无效。字符串内置方法
Section titled “字符串内置方法”Ruby 中的字符串是 String 类的对象,该类提供了一系列丰富的操作方法。要调用 String 方法,您通常使用 String 对象的实例:
my_string = "Initial Value"# or# my_string = String.new("Initial Value")示例:
#!/usr/bin/env ruby# frozen_string_literal: true
my_str = String.new("THIS IS A TEST")foo = my_str.downcase
puts "Lowercase string: #{foo}"这将产生以下结果:
Lowercase string: this is a test以下是一些常用的公共 String 方法(假定 str 是一个 String 对象)。有关完整列表,请参阅官方 Ruby 文档中关于 String 类的部分。
| ID | 方法及描述 |
|---|---|
| 1 | str % arg 使用格式说明符格式化字符串 (类似于 sprintf)。arg 可以是单个值或用于多个替换的数组。示例: "Hello %s" % "World"。为了可读性,通常更推荐使用字符串插值 (#{}) 或 Kernel#sprintf。 |
| 2 | str * integer 返回一个新字符串,其中包含 str 重复 integer 次。 |
| 3 | str + other_str 将 other_str 连接到 str 的末尾,返回一个新字符串。 |
| 4 | str << obj 将 obj 连接到 str 的末尾,就地修改 str。如果 obj 是 0-255 之间的 Integer,它会被转换为一个字符。返回 str。 |
| 5 | str <=> other_str 比较 str 和 other_str,返回 -1 (小于)、0 (等于) 或 1 (大于)。比较是区分大小写且基于字节值的。 |
| 6 | str == obj 测试相等性。如果 obj 不是 String,返回 false。否则,如果 str <=> obj 是 0,则返回 true。 |
| 7 | str =~ regexp 将 str 与正则表达式 regexp 进行匹配。返回匹配的起始索引,如果未找到匹配则返回 nil。设置全局变量,例如 $& (匹配的字符串)。对于布尔结果可以考虑使用 str.match?(regexp),或者使用 str.match(regexp) 获取 MatchData 对象,这种方式对全局变量的影响较小。 |
| 8 | str.capitalize 返回一个新的字符串,其中第一个字符转换为大写,其余转换为小写。 |
| 9 | str.capitalize! 与 capitalize 相同,但就地修改 str。如果未进行任何更改,返回 str 或 nil。 |
| 10 | str.casecmp(other_str) 字符串的忽略大小写比较。返回 -1、0 或 1。 str.casecmp?(other_str) (Ruby 2.4+ 版本) 返回 true 或 false。 |
| 11 | str.center(width, padstr=’ ‘) 返回一个长度为 width 的新字符串,其中 str 居中,并用 padstr 填充。 |
| 12 | str.chomp(separator=$/) 返回一个新字符串,其中从 str 的末尾移除给定的 separator (如果存在)。$/ 是输入记录分隔符,通常是换行符。如果 separator 是 "",它会移除所有尾部换行符。 |
| 13 | str.chomp!(separator=$/) 与 chomp 相同,但就地修改 str。返回 str 或 nil。 |
| 14 | str.chop 返回一个新字符串,其中最后一个字符被移除。如果字符串以 \r\n 结尾,则两者都被移除。 |
| 15 | str.chop! 与 chop 相同,但就地修改 str。返回 str 或 nil。 |
| 16 | str.concat(other_str)str << other_str 的别名。 |
| 17 | str.count(char_set_1, …, char_set_n) 计算 str 中的字符。当只有一个参数时,计算 char_set_1 中字符出现的次数。当有多个参数时,计算所有 char_set 交集中存在的字符。字符集可以使用 ^ 表示否定,使用 - 表示范围 (例如 "a-z")。 |
| 18 | WARNING: This method uses a weak, often DES-based, hashing algorithm based on the system’s crypt(3). It is NOT suitable for secure password storage in modern applications. Consider using libraries like bcrypt-ruby for robust password hashing. |
| 19 | str.delete(char_set_1, …, char_set_n) 返回 str 的一个副本,其中删除了其参数交集中的所有字符。 |
| 20 | str.delete!(char_set_1, …, char_set_n) 与 delete 相同,但就地修改 str。返回 str 或 nil。 |
| 21 | str.downcase 返回 str 的一个副本,其中所有大写字母都被替换为小写。如果支持 Unicode 大小写映射,则有效。 |
| 22 | str.downcase! 与 downcase 相同,但就地修改 str。返回 str 或 nil。 |
| 23 | str.dump 返回 str 的一个可打印版本,其中所有非打印字符都被 \nnn 表示法替换,特殊字符被转义。适用于调试或字符串字面量。 |
| 24 | str.each_char { |char| block } 将 str 的每个字符传递给块。如果没有提供块,则返回一个 Enumerator。 |
| 25 | str.each_byte { |byte| block } 将 str 的每个字节 (作为 0-255 的整数) 传递给块。如果没有提供块,则返回一个 Enumerator。 |
| 26 | str.each_line(separator=$/,chomp: false) { |line| block } 使用 separator 分割 str,将每个子字符串 (行) 传递给块。chomp 选项 (Ruby 2.6+ 版本) 会自动去除行的尾部空白。如果没有提供块,则返回一个 Enumerator。 |
| 27 | str.empty? 如果 str 的长度为零,返回 true。 |
| 28 | str.eql?(other) 如果两个字符串具有相同的长度和内容,则它们是 eql? 的。用于 Hash 的键相等性判断。 |
| 29 | str.gsub(pattern, replacement) or str.gsub(pattern) { |match| block } 返回 str 的一个副本,其中所有 pattern (String 或 Regexp) 的出现都被 replacement 或块的结果替换。 |
| 30 | str.gsub!(pattern, replacement) or str.gsub!(pattern) { |match| block } 与 gsub 相同,但就地修改 str。返回 str 或 nil。 |
| 31 | str[index] or str[start, length] or str[range] or str[regexp] or str[regexp, capture_group_index] or str[match_string] 元素引用 (切片)。访问字符或子字符串。负数索引从末尾开始计数。 |
| 32 | str[index] = new_val or str[start, length] = new_val … (similar to accessors) 元素赋值。替换字符串的一部分。 |
| 33 | str.hash 返回 str 的整数散列值。用于 Hash 对象。 |
| 34 | str.hex 将 str 的开头字符视为十六进制数字 (可选的 0x 前缀和符号),并返回相应的整数。出错时返回 0。 |
| 35 | str.include?(substring) 如果 str 包含给定的 substring,返回 true。 |
| 36 | str.index(substring_or_regexp [, offset]) 返回 substring_or_regexp 在 str 中第一次出现的索引,如果指定了 offset 则从该位置开始搜索。如果未找到,返回 nil。 |
| 37 | str.insert(index, other_str) 将 other_str 插入到 str 中索引 index 处的字符之前。修改 str。 |
| 38 | str.inspect 返回 str 的一个可打印版本,其中特殊字符被转义 (类似于 dump,但常用于 puts 和 p)。 |
| 39 | str.intern or str.to_sym 返回与 str 对应的 Symbol,如果它不存在则创建它。 |
| 40 | str.length 返回 str 的长度,以字符为单位 (尊重编码)。别名: size。 |
| 41 | str.ljust(width, padstr=’ ‘) 返回一个长度为 width 的新字符串,其中 str 左对齐,并用 padstr 填充。 |
| 42 | str.lstrip 返回 str 的一个副本,其中开头的空白字符被移除。 |
| 43 | str.lstrip! 就地从 str 中移除开头的空白字符。返回 str 或 nil。 |
| 44 | str.match(pattern [, pos]) 将 pattern 转换为 Regexp (如果尚未转换),并从 pos 位置开始与 str 进行匹配。返回一个 MatchData 对象或 nil。 |
| 45 | str.match?(pattern [, pos]) 类似于 match,但返回 true 或 false,并且不更新 $~ 或创建 MatchData 对象,这使得它在布尔检查时速度更快 (Ruby 2.4+ 版本)。 |
| 46 | str.oct 将 str 的开头字符视为八进制数字 (可选的符号),并返回相应的整数。出错时返回 0。 |
| 47 | str.replace(other_str) 用 other_str 替换 str 的内容。就地修改 str。 |
| 48 | str.reverse 返回一个新的字符串,其中包含 str 的字符的反向顺序。 |
| 49 | str.reverse! 就地反转 str。返回 str。 |
| 50 | str.rindex(substring_or_regexp [, offset]) 返回 substring_or_regexp 在 str 中最后一次出现的索引,如果指定了 offset 则从该位置向前搜索。如果未找到,返回 nil。 |
| 51 | str.rjust(width, padstr=’ ‘) 返回一个长度为 width 的新字符串,其中 str 右对齐,并用 padstr 填充。 |
| 52 | str.rstrip 返回 str 的一个副本,其中末尾的空白字符被移除。 |
| 53 | str.rstrip! 就地从 str 中移除末尾的空白字符。返回 str 或 nil。 |
| 54 | str.scan(pattern) or str.scan(pattern) { |match_capture_array| block } 遍历 str,匹配 pattern (Regexp 或 String)。对于每个匹配项,结果会添加到数组中或传递给块。如果 pattern 包含捕获组,则会为每个匹配项产生/返回一个捕获组数组。 |
| 55 | str.slice(…) / str.slice!(…)str[...] 和 str[...] = ... (破坏性切片) 的别名。slice! 删除指定部分并返回它。 |
| 56 | str.split(pattern=$;, limit=0) 根据 pattern (String 或 Regexp 定界符) 将 str 分割成子字符串,返回一个数组。$; 是默认的字段分隔符 (默认为 nil,表示按空白字符分割)。limit 控制字段的数量。 |
| 57 | str.squeeze([other_char_sets]*) 返回一个新字符串,其中连续重复的相同字符 (可选地仅限于 other_char_sets 中的字符) 被替换为一个单独的字符。 |
| 58 | str.squeeze!([other_char_sets]*) 与 squeeze 相同,但就地修改 str。返回 str 或 nil。 |
| 59 | str.strip 返回 str 的一个副本,其中开头的和末尾的空白字符被移除。 |
| 60 | str.strip! 就地从 str 中移除开头的和末尾的空白字符。返回 str 或 nil。 |
| 61 | str.sub(pattern, replacement) or str.sub(pattern) { |match| block } 返回 str 的一个副本,其中 pattern 第一次出现的地方被替换。 |
| 62 | str.sub!(pattern, replacement) or str.sub!(pattern) { |match| block } 与 sub 相同,但就地修改 str。返回 str 或 nil。 |
| 63 | str.succ or str.next 返回 str 的后继字符串 (例如 “a”.succ -> “b”, “9”.succ -> “10”, “az”.succ -> “ba”)。 |
| 64 | str.succ! or str.next! 就地将 str 修改为其后继。返回 str。 |
| 65 | str.swapcase 返回 str 的一个副本,其中大写字母字符被转换为小写,反之亦然。如果支持 Unicode,则有效。 |
| 66 | str.swapcase! 与 swapcase 相同,但就地修改 str。返回 str 或 nil。 |
| 67 | str.to_f 将 str 的开头字符解释为浮点数,并返回结果。出错时返回 0.0。 |
| 68 | str.to_i(base=10) 将 str 的开头字符解释为给定 base (2-36) 的整数,并返回结果。出错时返回 0。 |
| 69 | str.to_s or str.to_str 返回 self (字符串本身)。 |
| 70 | str.tr(from_str, to_str) 返回 str 的一个副本,其中 from_str 中的字符被 to_str 中对应的字符替换。支持 ^ 否定和 c1-c2 范围。 |
| 71 | str.tr!(from_str, to_str) 与 tr 相同,但就地修改 str。返回 str 或 nil。 |
| 72 | str.tr_s(from_str, to_str) 处理方式类似于 tr,然后压缩翻译后字符的连续重复项。 |
| 73 | str.tr_s!(from_str, to_str) 与 tr_s 相同,但就地修改 str。返回 str 或 nil。 |
| 74 | str.unpack(format) 根据 format 字符串解码 str (可能包含二进制数据),返回提取值的数组。请参阅下面的 unpack 指令。 |
| 75 | str.upcase 返回 str 的一个副本,其中所有小写字母都被替换为大写。如果支持 Unicode 大小写映射,则有效。 |
| 76 | str.upcase! 与 upcase 相同,但就地修改 str。返回 str 或 nil。 |
| 77 | str.upto(other_str, exclusive_end=false) { |s| block } 使用 succ 从 str 迭代到 other_str (默认为包含结束值),将每个值传递给块。如果没有提供块,则返回一个 Enumerator。 |
String unpack 指令
Section titled “String unpack 指令”String#unpack 方法使用由单字符指令组成的格式字符串来解码二进制数据。每个指令后可跟一个数字(重复计数)或 *(消耗剩余部分)。由于指令在某些情况下可能很复杂且依赖于平台(例如原生大小),请参阅 Ruby 文档以获取完整详细信息。
| 指令 | 返回 | 描述 |
|---|---|---|
| A | String | 任意二进制字符串 (移除尾部的 null 和空格)。 |
| a | String | 任意二进制字符串。 |
| B | String | 位字符串 (MSB 在前)。 |
| b | String | 位字符串 (LSB 在前)。 |
| C | Integer | 8 位无符号整数 (unsigned char)。 |
| c | Integer | 8 位有符号整数 (signed char)。 |
| D, d | Float | 双精度浮点数,原生格式。 |
| E | Float | 双精度浮点数,小端字节序。 |
| e | Float | 单精度浮点数,小端字节序。 |
| F, f | Float | 单精度浮点数,原生格式。 |
| G | Float | 双精度浮点数,网络 (大端) 字节序。 |
| g | Float | 单精度浮点数,网络 (大端) 字节序。 |
| H | String | 十六进制字符串 (MSB 字节的前半部分)。 |
| h | String | 十六进制字符串 (LSB 字节的前半部分)。 |
| I | Integer | 无符号整数,原生字节序 (大小可用 _ 或 ! 指定)。I_ 或 I! 表示原生 int 的大小。 |
| i | Integer | 有符号整数,原生字节序。i_ 或 i! 表示原生 int 的大小。 |
| L | Integer | 无符号 32 位整数,原生字节序 (L_, L!)。L> 表示大端,L< 表示小端。 |
| l | Integer | 有符号 32 位整数,原生字节序 (l_, l!)。l> 表示大端,l< 表示小端。 |
| M | String | Quoted-printable 编码字符串。 |
| m | String | Base64 编码字符串。 |
| N | Integer | 无符号 32 位整数,网络 (大端) 字节序。 |
| n | Integer | 无符号 16 位整数,网络 (大端) 字节序。 |
| P | String | 结构体指针 (固定长度字符串)。 |
| p | String | null 终止字符串指针。 |
| Q | Integer | 无符号 64 位整数,原生字节序 (Q_, Q!)。Q> 表示大端,Q< 表示小端。 |
| q | Integer | 有符号 64 位整数,原生字节序 (q_, q!)。q> 表示大端,q< 表示小端。 |
| S | Integer | 无符号 16 位整数,原生字节序 (S_, S!)。S> 表示大端,S< 表示小端。 |
| s | Integer | 有符号 16 位整数,原生字节序 (s_, s!)。s> 表示大端,s< 表示小端。 |
| U | Integer | UTF-8 字符作为整数码点。 |
| u | String | UU 编码字符串。 |
| V | Integer | 无符号 32 位整数,VAX (小端) 字节序。 |
| v | Integer | 无符号 16 位整数,VAX (小端) 字节序。 |
| w | Integer | BER 压缩整数。 |
| X | N/A | 向后跳过一个字节。 |
| x | N/A | 向前跳过一个字节 (null 字节)。 |
| Z | String | null 终止字符串 (移除尾部的 null)。使用 * 时,读取直到第一个 null。 |
| @ | N/A | 跳到长度参数给定的偏移量处。 |
unpack 方法对于解析二进制数据格式非常强大。
#!/usr/bin/env ruby# encoding: ascii-8bit # 常用于二进制数据
puts "abc \0\0abc \0\0".unpack('A6Z6').inspect # => ["abc", "abc "]puts "abc \0\0".unpack('a3a3').inspect # => ["abc", " \x00\x00"]puts "abc \0abc \0".unpack('Z*Z*').inspect # => ["abc ", "abc "]puts "aa".unpack('b8B8').inspect # => ["10000110", "01100001"] # 取决于 'a' 的 ASCII 值puts "aaa".unpack('H2H2c').inspect # => ["61", "61", 97] # ASCII 'a' 是 0x61,十进制 97puts "\xFE\xFF\xFE\xFF".unpack('sS').inspect # => [-2, 65534] # 在此示例中假定原生 short 为 16 位小端字节序puts "now=20is".unpack('M*').inspect # => ["now is"]puts "whole".unpack('x a x2 a X2 a X a X2 a').inspect # => ["h", "e", "l", "l", "o"] # 演示跳过
# 网络字节序整数示例data = [1024, 20480].pack('Nn') # 将两个整数打包成一个二进制字符串puts data.unpack('Nn').inspect # => [1024, 20480]有关 pack 和 unpack 指令的更详细示例和解释,请查阅官方 Ruby 文档中关于 Array#pack 和 String#unpack 的部分。