在详解 Ruby 中的正则表达式之前,我们先来看一段代码,就是看看 Ruby 如何使用正则表达式来匹配一个 URL 。
2.5.1 :001 > Regexp.new(/https?:\/\/[\S]+/) => /https?:\/\/[\S]+/ 2.5.1 :002 > url_matcher = _ => /https?:\/\/[\S]+/ 2.5.1 :003 > url_matcher.match('https://www.twle.cn/') => #<MatchData "https://www.twle.cn/"> 2.5.1 :004 > 2.5.1 :005 > 2.5.1 :006 > 2.5.1 :007 > # Wi love Ruby!
上面这段代码使用正则表达式来匹配一个网址。如果你用过其它语言的正则表达式,那么对 /https?:\/\/[\S]+/
应该很熟悉了。
Ruby 中的正则表达式类
首先,Ruby 中的正则表达式也是一个对象,所有和正则表达式相关的逻辑都封装在 Regexp
类中。
同时, Ruby 还提供了三种初始化一个正则表达式实例的方法
Regexp.new(/.*/).class # => Regexp
/.*/.class # => Regexp
%r{.*}.class # => Regexp
OK ,既然知道了如何创建正则表达式,那接下来的问题来了: 如何将此 Regexp 与一个字符串相匹配 ?
MetaData 类
Regexp
类提供了一个 Regexp#match
方法,该方法将一个字符串作为参数进行测试。
/I love Ruby/.match('I love Ruby') # => #< MatchData "I love Ruby">
Regexp#match
方法会返回一个 MetaData
类的实例。这个 MetaData
类的实例封装了所有的模式匹配的结果。
我们诚挚的邀请你访问官方的 文档 ,了解 MetaData 类能够做些什么。例如,可以使用 MatchData#to_a
方法来迭代结果。
Ruby 中和正则表达式相关的魔术变量
Ruby 提供了一组跟正则表达式相关的魔术变量,Ruby 会使用 MetaData 的新实例来给这些变量自动赋值。
下面的代码是一些魔术变量的使用示例
/(I love) (Ruby)/.match("Yes, I love Ruby. We're cool.") # $~ returns the latest instance of MatchData $~ # => #<MatchData "I love Ruby" 1:"I love" 2:"Ruby"> $& # => "I love Ruby" (The matching portion of the String) $` # => "Yes, " (Equivalent to MatchData#pre_match method) $' # => ". We're cool." (Equivalent to MatchData#post_match method) $1 # => "I love" $2 # => "Ruby" $3 # => nil
模式匹配运算符 =~
为了简化正则表达式的使用,Ruby 提供了语法糖运算符 =~
,运算符可以将正则表达式与字符串匹配,并返回匹配到的模式结果
/(devscoop)/ =~ "http://ruby.devscoop.fr" # => 12 "http://ruby.devscoop.fr" =~ /(devscoop)/ # => 12 # Note that the operator returns nil if no matching found /lol/ =~ "It's not funny" # => nil
请注意,当 =~
方法返回时,会自动设置所有正则表达式相关的魔法变量,因为 =~
运算符会自动实例化正则表达式 ( Regexp ) 与字符串 ( String ) 匹配结果的的 MatchData
命名捕获 ( Name Capture )
当 命名捕获 功能与 =~
运算符一起使用时,就具有强大的机制,可以使用分配给 Regexp 实例的组的名称自动将匹配组的结果分配到变量中
if /(?<newsletter>devscoop)/ =~ 'http://ruby.devscoop.fr' p newsletter # => "devscoop" end
Regexp#match
方法也提供了命名捕获功能,和 =~
主要的区别在于 match
方法不会自动创建变量。
另一方面,通过使用 MatchData#[]
方法来使用返回的 MatchData 实例的命名捕获
if projects = /(?<newsletter>devscoop)/.match('http://ruby.devscoop.fr') p projects['newsletter'] # => "devscoop" end
延伸阅读
Ruby 还提供了许多与正则表达式有关的方法,比如
但这些方法不是集成到正则表达式核心中的,而是分布在字符串中。所以,本章节,我们并未介绍它们。
如果你想要了解详情,可以点击各自的链接到官方文档中浏览。
结束语
Ruby 正则表达式的方法真的是很少很少,不过功能一点也没有减少,尤其是它的魔术变量