Ruby 正则表达式(一文讲透)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言

正则表达式(Regular Expression)是编程领域中一种强大的文本处理工具,尤其在需要精准匹配、提取或替换字符串的场景中,它能显著提升开发效率。在 Ruby 这门语言中,正则表达式与语法深度融合,提供了简洁且灵活的使用方式。无论是验证用户输入、解析日志文件,还是自动化文本编辑,掌握 Ruby 正则表达式 都是开发者进阶路上的重要一步。本文将从基础语法到高级技巧,结合实际案例,帮助读者系统性地理解这一工具的核心逻辑与应用场景。


基础语法:正则表达式的“乐高积木”

正则表达式可以看作一组“乐高积木”,通过组合不同的符号和规则,构建出能匹配特定文本模式的表达式。在 Ruby 中,正则表达式通常用 /.../ 包裹,例如 /ruby/ 表示匹配字符串中的“ruby”字符序列。

1. 字符匹配

最基本的正则表达式由普通字符组成,例如:

pattern = /hello/  
puts "hello world" =~ pattern  # 输出 0(匹配起始位置)  

若需要匹配特殊符号(如 .*),需使用反斜杠 \ 转义:

pattern = /\.\*/  
puts "a.b*c" =~ pattern       # 输出 1  

2. 元字符:赋予正则表达式“超能力”

元字符是正则表达式的核心,它们代表特定的匹配规则:

元字符含义示例
.匹配任意单个字符(除换行符)/a.c/ 匹配 "abc"、"a3c"
^匹配字符串开头/^start/ 匹配 "start_here"
$匹配字符串结尾/end$/ 匹配 "finish_end"
|或关系/cat|dog/ 匹配 "cat"或"dog"

比喻:元字符如同“魔法符文”,赋予普通字符特殊能力。例如 . 可以像“通配符”一样匹配任意字符,而 ^$ 则像“锚点”,固定匹配的起止位置。


量词:控制匹配的“贪婪程度”

量词用于指定字符或组的重复次数,常见的包括:

量词含义示例
*出现 0 次或多次/a*/ 匹配空字符串、"a"、"aaa"
+出现 1 次或多次/a+/ 匹配 "a"、"aa",不匹配空
?出现 0 次或 1 次/colou?r/ 匹配 "color"或"colour"
{n}出现恰好 n 次/a{3}/ 匹配 "aaa"
{n,}出现至少 n 次/a{2,}/ 匹配 "aa"、"aaaa"

案例:验证一个简单密码规则(长度 6~12 字符,仅含字母和数字):

password = "P@ssw0rd"  
puts password =~ /^[a-zA-Z0-9]{6,12}$/  

常用方法:Ruby 中的正则表达式操作

Ruby 提供了丰富的方法来与正则表达式交互,以下是最常用的几种:

1. String#matchRegexp#match

用于检测字符串是否匹配正则表达式,并返回匹配数据:

result = "apple pie".match(/apple/)  
puts result[0]      # 输出 "apple"  
puts result.offset(0) # 输出 [0, 5](起始和结束索引)  

2. String#=~

返回匹配的起始索引,若未匹配则返回 nil

puts "ruby regex" =~ /regex/  # 输出 5  

3. String#scan

提取所有匹配项,返回数组:

text = "2023-09-15 and 2024-01-01"  
dates = text.scan(/\d{4}-\d{2}-\d{2}/)  
puts dates.inspect             # 输出 ["2023-09-15", "2024-01-01"]  

4. String#gsubString#sub

用于替换匹配内容:

text = "ID: 12345"  
new_text = text.gsub(/\d/, "*")  
puts new_text                  # 输出 "ID: *****"  

进阶技巧:组捕获与修饰符

1. 组捕获:提取子匹配项

通过 () 将部分表达式分组,可以单独捕获其内容:

url = "https://example.com/path"  
match_data = url.match(/(https?):\/\/([a-z.]+)(\/.*)?/)  
puts "协议:#{match_data[1]}"     # 输出 "https"  
puts "域名:#{match_data[2]}"     # 输出 "example.com"  
puts "路径:#{match_data[3]}"     # 输出 "/path"  

2. 修饰符:改变匹配行为

在正则表达式末尾添加修饰符,可调整匹配规则:

修饰符含义
i忽略大小写/apple/i 匹配 "Apple"或"APPLE"
m多行模式(改变 ^$ 行为)
x允许空白和注释(增强可读性)

示例:使用 x 修饰符清晰表达邮箱正则:

email_regex = /  
  \A           # 匹配开头  
  [\w+\-.]+    # 用户名部分  
  @            # @ 符号  
  [a-z\d\-]+\. # 域名部分(简化版)  
  [a-z]+\z     # 结尾  
  /ix          # i(忽略大小写)、x(允许注释)  

3. 贪婪与非贪婪匹配

默认量词(如 *+)是“贪婪”的,会尽可能多匹配字符。添加 ? 可变为非贪婪模式:

puts "abc123xyz".match(/(\D+)(\d+)/)[0] # 输出 "abc123"(非预期)  
puts "abc123xyz".match(/(\D+?)(\d+)/)[0] # 输出 "abc"  

实战案例:正则表达式的应用场景

案例 1:验证手机号格式

中国手机号格式为 11 位数字,以 1 开头,第二位为 3-9 中的数字:

def valid_phone?(phone)  
  phone =~ /^1[3-9]\d{9}$/  
end  
puts valid_phone?("13800138000") # 输出 true  

案例 2:提取网页中的链接

从 HTML 内容中提取所有 <a> 标签的 href 属性:

html = '<a href="https://example.com">Link</a> <a href="/about">About</a>'  
urls = html.scan(/href=["'](.*?)["']/).flatten  
puts urls.inspect  # 输出 ["https://example.com", "/about"]  

案例 3:替换敏感词

gsub 方法批量替换文本中的敏感词:

sensitive_words = ["敏感词1", "敏感词2"]  
text = "这是一段包含敏感词1和敏感词2的内容"  
clean_text = text.gsub(/#{Regexp.union(sensitive_words)}/, "[敏感]")  
puts clean_text  # 输出 "这是一段包含[敏感]和[敏感]的内容"  

结论

Ruby 正则表达式 是文本处理的利器,其简洁的语法和强大的功能能显著提升开发效率。从基础的字符匹配到进阶的组捕获、修饰符应用,开发者可以通过系统性学习逐步掌握这一工具。无论是验证用户输入、解析复杂数据,还是自动化文本编辑,正则表达式都能提供高效解决方案。

建议读者通过实际项目实践正则表达式,例如:

  1. 编写一个邮箱格式验证器;
  2. 从日志文件中提取特定时间戳;
  3. 自动化替换文本中的特定模式。

通过不断练习和探索,正则表达式将成为你代码工具箱中不可或缺的“瑞士军刀”。

最新发布