我正在阅读一个regex group matching问题,我发现有两种方法可以从正则表达式中引用捕获组,即
string.match(/(^.*)(:)(.*)/i).captures
if match =~ /(^.*)(:)(.*)/i
哪个更好?使用1),为了安全起见,你必须使用if语句来防止nils,那么为什么不提取信息呢?而不是第二步调用字符串捕获方法。所以选项2)对我来说看起来更方便。
答案 0 :(得分:4)
对于简单的任务,直接访问伪变量$1
等可能很简单,但是当事情变得复杂时,通过MatchData
实例访问事物(几乎)是唯一的方法
例如,假设您正在嵌套gsub
:
string1.gsub(regex1) do |string2|
string2.gsub(regex2) do
... # Impossible/difficult to refer to match data of outer loop
end
end
在内部循环中,假设您想要引用外部gsub
的捕获组。调用$1
,$2
等不会给出正确的结果,因为最后一个匹配数据已经通过执行内部gsub
循环而发生了变化。这将是bug的来源。
有必要通过匹配数据引用捕获的组:
string1.gsub(regex1) do |string2|
m1 = $~
string2.gsub(regex2) do
m2 = $~
... # match data of the outer loop can be accessed via `m1`.
# match data of the inner loop can be accessed via `m2`.
end
end
简而言之,如果你想为简单的任务做短暂的hackish事情,你可以使用伪变量。如果您希望保持代码更加结构化和可扩展,则应通过匹配数据访问数据。
答案 1 :(得分:0)
忍不住想,目前接受的2013年答案已经过时。从2.4.6开始,Ruby有了named_captures
,可以像这样使用。只需在捕获组中添加?<some_name>
语法即可。
/(\w)(\w)/.match("ab").captures # => ["a", "b"]
/(\w)(\w)/.match("ab").named_captures # => {}
/(?<some_name>\w)(\w)/.match("ab").captures # => ["a"]
/(?<some_name>\w)(\w)/.match("ab").named_captures # => {"some_name"=>"a"}
更相关的是,您可以按名称引用命名捕获!
result = /(?<some_name>\w)(\w)/.match("ab")
result["some_name"] # => "a"