组匹配,在1行上分配变量

我当前正在尝试将一个字符串重新解析为多个变量。示例字符串:

ryan_string = "RyanOnRails: This is a test"

我将它与这个 regexp 进行了匹配,共有3组:

ryan_group = ryan_string.scan(/(^.*)(:)(.*)/i)

现在,要进入每个群组,我必须这样做:

ryan_group[0][0] (first group) RyanOnRails
ryan_group[0][1] (second group) :
ryan_group[0][2] (third group) This is a test

这看起来很荒谬,感觉我做错了什么。我希望能够做到这样的事情:

g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)

这可能吗? 还是有比我做的更好的方法?

113231 次浏览

您可以使用 匹配或 = ~ 来代替,它会给您一个匹配,您可以以相同的方式访问匹配数据,或者只使用特殊的匹配变量 $1,$2,$3

比如:

if ryan_string =~ /(^.*)(:)(.*)/i
first = $1
third = $3
end

你不希望 scan为此,因为它没有什么意义。您可以使用返回 MatchData对象的 String#match,然后您可以调用 #captures来返回捕获的 Array。就像这样:

#!/usr/bin/env ruby


string = "RyanOnRails: This is a test"
one, two, three = string.match(/(^.*)(:)(.*)/i).captures


p one   #=> "RyanOnRails"
p two   #=> ":"
p three #=> " This is a test"

请注意,如果没有找到匹配,String#match将返回零,因此这样的方法可能会更好:

if match = string.match(/(^.*)(:)(.*)/i)
one, two, three = match.captures
end

尽管 scan对此没有什么意义。它仍然执行这项工作,您只需要首先平坦返回的 Array。one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten

scan()将在字符串中找到正则表达式的所有非重叠匹配项,因此它返回的不是您所期望的组的数组,而是数组的数组。

您可能最好使用 match(),然后使用 MatchData#captures获得捕获数组:

g1, g2, g3 = ryan_string.match(/(^.*)(:)(.*)/i).captures

然而,如果你想的话,你也可以使用 scan():

g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)[0]

您可以命名捕获的匹配项

string = "RyanOnRails: This is a test"
/(?<one>^.*)(?<two>:)(?<three>.*)/i =~ string
puts one, two, three

如果您逆转字符串和正则表达式的顺序,那么它将不工作。

您必须决定它是否是一个好主意,但是 ruby regexp 可以(自动地)为您提供 定义局部变量

我还不确定这个特性是不是很棒或者完全疯狂,但是你的正则表达式可以定义局部变量。

ryan_string = "RyanOnRails: This is a test"
/^(?<webframework>.*)(?<colon>:)(?<rest>)/ =~ ryan_string
# This defined three variables for you. Crazy, but true.
webframework # => "RyanOnRails"
puts "W: #{webframework} , C: #{colon}, R: #{rest}"

(看看 http://ruby-doc.org/core-2.1.1/Regexp.html,搜索“ local variable”)。

注: 正如在评论中指出的那样,我看到@toonsend (https://stackoverflow.com/a/21412455)对这个问题有一个类似的早期答案。我不认为我是在“偷窃”,但如果你想公平地赞扬和尊重第一个答案,请随意:)我希望没有动物受到伤害。