Ruby中对nil使用匹配运算符的预期行为及捕获变量疑问
在Ruby中对nil使用匹配运算符(=~)的预期行为及捕获变量变化
先看你给出的代码:
"a1c" =~ /.*(\d).*/ puts $1 nil =~ /.*(\d).*/ puts $1 puts $1.nil?
运行结果是:
1 1 false
你疑惑的核心点在于:为什么对nil执行匹配后,$1没有被重置为nil?原因可以从两方面拆解:
nil =~ /regex/的实际调用逻辑nil本身没有实现=~方法,Ruby会自动把这个调用转换为/regex/ =~ nil,也就是转而调用正则表达式的=~方法,将nil作为参数传入。全局捕获变量的更新规则
- 当调用字符串的
=~方法时(比如"abc" =~ /regex/),无论匹配成功还是失败,都会更新全局捕获变量:成功时设置为捕获到的内容,失败时将所有捕获变量重置为nil。 - 当调用正则表达式的
=~方法时(比如/regex/ =~ nil),只有匹配成功才会更新捕获变量;如果匹配失败(比如传入nil这种无法被正则匹配的对象),不会修改已有的捕获变量,它们会保留之前的取值。
对应到你的代码流程:
- 第一行
"a1c" =~ /.*(\d).*/调用字符串的=~,匹配成功,$1被设置为"1"。 - 第二行
nil =~ /.*(\d).*/实际是调用正则的=~,传入nil后匹配失败,此时不会触动$1,所以它仍然是"1"。 - 因此后续打印
$1还是1,$1.nil?返回false。
内容的提问来源于stack exchange,提问作者Zack
相关产品推荐
相关产品推荐

