Ruby Regexp组匹配,在1行上分配variables
我目前正试图将一个string重新映射到多个variables。 示例string:
ryan_string = "RyanOnRails: This is a test"
我用这个正则expression式匹配它,有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)
这可能吗? 还是有比我更好的方法吗?
你不想scan
这个,因为它没有什么意义。 您可以使用String#match
返回一个MatchData
对象,然后调用#captures
返回一个捕获数组。 像这样的东西:
#!/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
确实没有什么意义。 它仍然可以完成这个工作,你只需要先将返回的数组展平。 one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten
你可以使用Match或者=〜来代替,这样可以给你一个单独的匹配,你可以以相同的方式访问匹配数据,也可以使用特殊的匹配variables$ 1,$ 2,$ 3
就像是:
if ryan_string =~ /(^.*)(:)(.*)/i first = $1 third = $3 end
您可以命名您捕获的匹配
string = "RyanOnRails: This is a test" /(?<one>^.*)(?<two>:)(?<three>.*)/i =~ string puts one, two, three
如果你颠倒了string和正则expression式的顺序,它是行不通的。
scan()
会在你的string中find正则expression式的所有非重叠匹配,所以不是像你期待的那样返回一个你的组的数组,而是返回一个数组数组。
你可能最好使用match()
,然后使用MatchData#captures
数组:
g1, g2, g3 = ryan_string.match(/(^.*)(:)(.*)/i).captures
但是,如果您想要使用scan()
也可以这样做:
g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)[0]
你必须决定是否是一个好主意,但ruby正则expression式可以为你定义局部variables!
我还不确定这个function是真棒还是完全疯狂,但你的正则expression式可以定义局部variables。
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 ,search“本地variables”)。
注意:正如在评论中指出的那样,我发现@toonsend( https://stackoverflow.com/a/21412455 )对这个问题有一个相似和较早的答案。 我不认为我是“偷”,但如果你想公平地赞美和荣誉的第一个答案,请随时:)我希望没有动物受到伤害。