Ruby 字符串(String)
字符串是编程中最常用的数据类型之一,用于存储和操作文本数据。Ruby中的字符串功能强大且灵活,提供了丰富的内置方法来处理文本。本章将详细介绍Ruby中字符串的创建、操作和处理方法。
🎯 字符串基础
字符串定义
Ruby支持多种方式定义字符串,每种方式都有其特定的用途:
ruby
# 单引号字符串(不解析转义字符和插值)
name = '张三'
message = 'Hello\nWorld' # \n不会被解析为换行符
puts message # 输出: Hello\nWorld
# 双引号字符串(解析转义字符和插值)
name = "李四"
age = 25
message = "你好, #{name}! 你今年#{age}岁了。"
greeting = "Hello\nWorld" # \n会被解析为换行符
puts greeting
# 输出:
# Hello
# World
# 多行字符串(heredoc语法)
poem = <<~TEXT
静夜思
床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。
TEXT
puts poem
# 输出:
# 静夜思
# 床前明月光,
# 疑是地上霜。
# 举头望明月,
# 低头思故乡。
# 使用%q和%Q定义字符串
single_quoted = %q(这是一个'单引号'字符串)
double_quoted = %Q(这是一个"双引号"字符串,包含#{name})
puts single_quoted # 这是一个'单引号'字符串
puts double_quoted # 这是一个"双引号"字符串,包含李四字符串编码
Ruby 1.9之后支持多种字符编码:
ruby
# 查看字符串编码
str = "你好"
puts str.encoding # UTF-8
# 指定编码
str_with_encoding = "Hello".force_encoding("ASCII")
puts str_with_encoding.encoding # ASCII
# 转换编码
utf8_str = "你好".encode("UTF-8")
puts utf8_str🔤 字符串操作
字符串连接
ruby
# 使用+连接
first_name = "张"
last_name = "三"
full_name = first_name + last_name
puts full_name # 张三
# 使用<<连接(修改原字符串)
greeting = "你好, "
greeting << "世界!"
puts greeting # 你好, 世界!
# 使用concat方法
message = "Hello".concat(" ", "World")
puts message # Hello World
# 使用插值(推荐)
name = "Ruby"
version = "3.0"
info = "#{name} #{version}"
puts info # Ruby 3.0字符串重复和长度
ruby
# 重复字符串
line = "-" * 20
puts line # --------------------
# 获取字符串长度
str = "Hello, 世界!"
puts str.length # 10
puts str.size # 10
puts str.bytesize # 13 (字节长度)
# 检查是否为空
empty_str = ""
puts empty_str.empty? # true
puts " ".empty? # false
puts " ".strip.empty? # true字符串比较
ruby
# 基本比较
puts "hello" == "hello" # true
puts "hello" == "Hello" # false (区分大小写)
# 忽略大小写比较
puts "hello".casecmp("Hello") # 0 (相等)
puts "a".casecmp("B") # -1 (小于)
puts "c".casecmp("B") # 1 (大于)
# 包含关系
puts "Hello, World!".include?("World") # true
puts "Hello, World!".start_with?("Hello") # true
puts "Hello, World!".end_with?("World!") # true🔍 字符串查找和替换
查找子字符串
ruby
text = "Hello, Ruby World! Welcome to Ruby programming."
# 查找位置
puts text.index("Ruby") # 7
puts text.rindex("Ruby") # 31 (从右边查找)
puts text.index("Python") # nil (未找到)
# 使用正则表达式查找
puts text.index(/R\w+/) # 7 (匹配以R开头的单词)
# 获取字符
puts text[0] # H
puts text[7] # R
puts text[-1] # .
puts text[7, 4] # Ruby
puts text[7..10] # Ruby替换子字符串
ruby
text = "Hello, Ruby World! Welcome to Ruby programming."
# 替换第一个匹配项
new_text = text.sub("Ruby", "Python")
puts new_text # Hello, Python World! Welcome to Ruby programming.
# 替换所有匹配项
new_text = text.gsub("Ruby", "Python")
puts new_text # Hello, Python World! Welcome to Python programming.
# 使用正则表达式替换
new_text = text.gsub(/R\w+/, "Python")
puts new_text # Hello, Python World! Welcome to Python programming.
# 使用块进行复杂替换
new_text = text.gsub(/\b\w+\b/) { |word| word.upcase }
puts new_text # HELLO, RUBY WORLD! WELCOME TO RUBY PROGRAMMING.🔄 字符串变换
大小写转换
ruby
text = "Hello, World!"
# 大小写转换
puts text.upcase # HELLO, WORLD!
puts text.downcase # hello, world!
puts text.capitalize # Hello, world!
puts text.swapcase # hELLO, wORLD!
# 首字母大写
title = "hello world"
puts title.capitalize # Hello world
# 每个单词首字母大写
sentence = "hello world ruby programming"
puts sentence.split.map(&:capitalize).join(" ") # Hello World Ruby Programming去除空白字符
ruby
text = " Hello, World! "
# 去除两边空白
puts text.strip # Hello, World!
puts text.lstrip # Hello, World!
puts text.rstrip # Hello, World!
# 去除所有空白
compact_text = " Hello World ! "
puts compact_text.gsub(/\s+/, " ").strip # Hello World !分割和连接
ruby
# 分割字符串
sentence = "apple,banana,orange,grape"
fruits = sentence.split(",")
puts fruits.inspect # ["apple", "banana", "orange", "grape"]
# 使用正则表达式分割
text = "apple banana\torange\ngrape"
words = text.split(/\s+/)
puts words.inspect # ["apple", "banana", "orange", "grape"]
# 连接数组为字符串
puts fruits.join(", ") # apple, banana, orange, grape
puts fruits.join(" | ") # apple | banana | orange | grape🧮 字符串格式化
sprintf和格式化
ruby
name = "张三"
age = 25
score = 95.5
# 使用sprintf格式化
formatted = sprintf("姓名: %s, 年龄: %d, 分数: %.1f", name, age, score)
puts formatted # 姓名: 张三, 年龄: 25, 分数: 95.5
# 使用%操作符
formatted = "姓名: %s, 年龄: %d, 分数: %.1f" % [name, age, score]
puts formatted # 姓名: 张三, 年龄: 25, 分数: 95.5
# 数字格式化
puts "%04d" % 42 # 0042 (补零)
puts "%.2f" % 3.14159 # 3.14 (保留两位小数)
puts "%10s" % "Ruby" # " Ruby" (右对齐)
puts "%-10s" % "Ruby" # "Ruby " (左对齐)字符串插值
ruby
name = "Ruby"
version = "3.0"
release_date = "2020-12-25"
# 基本插值
info = "#{name} #{version} 发布于 #{release_date}"
puts info # Ruby 3.0 发布于 2020-12-25
# 表达式插值
x, y = 10, 20
result = "#{x} + #{y} = #{x + y}"
puts result # 10 + 20 = 30
# 控制插值格式
price = 123.456
formatted_price = "价格: #{"%.2f" % price}"
puts formatted_price # 价格: 123.46🔧 字符串实用方法
字符串验证
ruby
# 检查字符串类型
puts "123".numeric? # true (需要自定义方法)
puts "123".match?(/^\d+$/) # true (使用正则表达式)
# 自定义验证方法
class String
def numeric?
!!Float(self)
rescue ArgumentError, TypeError
false
end
def alphabetic?
match?(/^[a-zA-Z]+$/)
end
def alphanumeric?
match?(/^[a-zA-Z0-9]+$/)
end
end
puts "123".numeric? # true
puts "abc".alphabetic? # true
puts "abc123".alphanumeric? # true字符串处理实用技巧
ruby
# 安全导航(避免nil错误)
name = nil
puts name&.upcase # nil (不会抛出错误)
puts name&.length # nil
# 空值处理
def safe_upcase(str)
str&.upcase || ""
end
puts safe_upcase("hello") # HELLO
puts safe_upcase(nil) # ""
# 字符串截断
def truncate(str, length = 20, omission = "...")
return str if str.length <= length
str[0, length - omission.length] + omission
end
long_text = "这是一段非常长的文本,需要被截断处理"
puts truncate(long_text, 15) # 这是一段非常长的文...🎯 字符串实践示例
文本处理工具
ruby
class TextProcessor
def initialize(text)
@text = text
end
# 统计单词数量
def word_count
@text.split(/\s+/).length
end
# 统计字符数量(不含空格)
def char_count(exclude_spaces = true)
if exclude_spaces
@text.gsub(/\s/, "").length
else
@text.length
end
end
# 查找最常见的单词
def most_common_word
words = @text.downcase.gsub(/[^\w\s]/, "").split(/\s+/)
word_count = Hash.new(0)
words.each { |word| word_count[word] += 1 }
word_count.max_by { |word, count| count }&.first
end
# 替换敏感词
def censor_words(bad_words, replacement = "*")
result = @text
bad_words.each do |word|
pattern = Regexp.escape(word)
result = result.gsub(/#{pattern}/i) do |match|
replacement * match.length
end
end
result
end
# 生成摘要
def summarize(max_words = 10)
words = @text.split(/\s+/)
if words.length <= max_words
@text
else
words[0, max_words].join(" ") + "..."
end
end
end
# 使用文本处理器
text = "Ruby是一种动态、开源的编程语言,专注于简洁和效率。Ruby的语法优雅,易于阅读和编写。"
processor = TextProcessor.new(text)
puts "单词数量: #{processor.word_count}" # 单词数量: 26
puts "字符数量: #{processor.char_count}" # 字符数量: 45
puts "摘要: #{processor.summarize(10)}"
# 摘要: Ruby是一种动态、开源的编程语言,专注于简洁和效率。Ruby的语法优雅,易于阅读和...
# 敏感词过滤示例
content = "这个产品真的很烂,质量太差了!"
bad_words = ["烂", "差"]
filtered = processor.censor_words(bad_words)
puts filtered # 这个产品真的很**,质量太*了!字符串验证器
ruby
class StringValidator
def self.email?(str)
pattern = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
str.match?(pattern)
end
def self.phone?(str)
pattern = /\A1[3-9]\d{9}\z/
str.match?(pattern)
end
def self.url?(str)
pattern = /\Ahttps?:\/\/[\w\-]+(\.[\w\-]+)+[/#?]?.*\z/
str.match?(pattern)
end
def self.strong_password?(str)
# 至少8位,包含大小写字母、数字和特殊字符
return false if str.length < 8
has_upper = str.match?(/[A-Z]/)
has_lower = str.match?(/[a-z]/)
has_digit = str.match?(/\d/)
has_special = str.match?(/[!@#$%^&*(),.?":{}|<>]/)
has_upper && has_lower && has_digit && has_special
end
def self.chinese_id_card?(str)
# 简化的身份证验证(18位数字,最后一位可能是X)
pattern = /\A\d{17}[\dXx]\z/
str.match?(pattern)
end
end
# 使用验证器
puts StringValidator.email?("user@example.com") # true
puts StringValidator.email?("invalid.email") # false
puts StringValidator.phone?("13812345678") # true
puts StringValidator.url?("https://www.example.com") # true
puts StringValidator.strong_password?("Password123!") # true
puts StringValidator.chinese_id_card?("110101199001011234") # true字符串格式化工具
ruby
class StringFormatter
# 驼峰命名转换为蛇形命名
def self.camel_to_snake(str)
str.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
.downcase
end
# 蛇形命名转换为驼峰命名
def self.snake_to_camel(str)
str.split('_').map.with_index { |word, i|
i == 0 ? word : word.capitalize
}.join
end
# 格式化电话号码
def self.format_phone(phone)
phone.gsub(/\D/, "") # 移除非数字字符
.gsub(/(\d{3})(\d{4})(\d{4})/, '\1-\2-\3')
end
# 格式化金额
def self.format_currency(amount, currency = "¥")
"#{currency}#{'%.2f' % amount.to_f}"
end
# 格式化日期
def self.format_date(date_str, format = :cn)
case format
when :cn
date_str.gsub(/(\d{4})-(\d{2})-(\d{2})/, '\1年\2月\3日')
when :us
date_str.gsub(/(\d{4})-(\d{2})-(\d{2})/, '\2/\3/\1')
else
date_str
end
end
end
# 使用格式化工具
puts StringFormatter.camel_to_snake("userName") # user_name
puts StringFormatter.camel_to_snake("XMLHttpRequest") # xml_http_request
puts StringFormatter.snake_to_camel("user_name") # userName
puts StringFormatter.format_phone("13812345678") # 138-1234-5678
puts StringFormatter.format_currency(1234.5) # ¥1234.50
puts StringFormatter.format_date("2023-12-25", :cn) # 2023年12月25日📊 字符串性能优化
字符串构建优化
ruby
# 低效的方式(每次连接都创建新对象)
def inefficient_build(strings)
result = ""
strings.each { |str| result += str }
result
end
# 高效的方式(使用<<修改原对象)
def efficient_build(strings)
result = ""
strings.each { |str| result << str }
result
end
# 最高效的方式(使用数组连接)
def most_efficient_build(strings)
strings.join("")
end
# 使用StringIO处理大量字符串操作
require 'stringio'
def build_with_stringio(parts)
io = StringIO.new
parts.each { |part| io << part }
io.string
end字符串冻结
ruby
# 冻结字符串避免修改
CONSTANT_STRING = "这是一个常量字符串".freeze
# 冻结字符串字面量(Ruby 3.0默认)
# frozen_string_literal: true
# str = "这将自动冻结"
# 检查字符串是否冻结
puts CONSTANT_STRING.frozen? # true🎯 字符串最佳实践
1. 选择合适的字符串定义方式
ruby
# 对于简单文本,使用双引号(支持插值)
name = "张三"
greeting = "你好, #{name}!"
# 对于包含特殊字符的文本,使用单引号
sql = 'SELECT * FROM users WHERE name = "张三"'
# 对于多行文本,使用heredoc
template = <<~HTML
<div class="user-card">
<h1>#{name}</h1>
<p>欢迎使用我们的服务</p>
</div>
HTML2. 安全处理用户输入
ruby
class SafeStringHandler
# 转义HTML特殊字符
def self.escape_html(str)
str.gsub(/&/, "&")
.gsub(/</, "<")
.gsub(/>/, ">")
.gsub(/"/, """)
.gsub(/'/, "'")
end
# 安全的字符串截断
def self.safe_truncate(str, length, omission = "...")
return str if str.nil? || str.length <= length
str[0, length - omission.length] + omission
end
# 清理字符串(移除控制字符)
def self.sanitize(str)
str.gsub(/[[:cntrl:]]/, "")
end
end
# 使用安全处理
user_input = "<script>alert('XSS')</script>"
safe_output = SafeStringHandler.escape_html(user_input)
puts safe_output # <script>alert('XSS')</script>3. 字符串编码处理
ruby
class EncodingHandler
# 统一转换为UTF-8
def self.to_utf8(str)
return str if str.encoding == Encoding::UTF_8
str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
end
# 检测并处理编码
def self.handle_encoding(str)
# 检测编码
detected_encoding = CharlockHolmes::EncodingDetector.detect(str)
if detected_encoding && detected_encoding[:encoding] != 'UTF-8'
str.force_encoding(detected_encoding[:encoding])
.encode('UTF-8', invalid: :replace, undef: :replace)
else
str
end
rescue
str.force_encoding('UTF-8')
end
end📚 下一步学习
掌握了Ruby字符串操作后,建议继续学习:
- Ruby 数组(Array) - 学习数组数据结构的使用
- Ruby 哈希(Hash) - 掌握键值对数据结构
- Ruby 正则表达式 - 学习强大的文本匹配和处理
- Ruby 文件处理及I/O - 了解文件读写操作
继续您的Ruby学习之旅吧!