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#match
和 Regexp#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#gsub
和 String#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 正则表达式 是文本处理的利器,其简洁的语法和强大的功能能显著提升开发效率。从基础的字符匹配到进阶的组捕获、修饰符应用,开发者可以通过系统性学习逐步掌握这一工具。无论是验证用户输入、解析复杂数据,还是自动化文本编辑,正则表达式都能提供高效解决方案。
建议读者通过实际项目实践正则表达式,例如:
- 编写一个邮箱格式验证器;
- 从日志文件中提取特定时间戳;
- 自动化替换文本中的特定模式。
通过不断练习和探索,正则表达式将成为你代码工具箱中不可或缺的“瑞士军刀”。