如何在ruby中进行命名捕获

时间:2013-09-16 10:22:57

标签: ruby regex

我想命名从扫描中获取的字符串的捕获。怎么做?

"555-333-7777".scan(/(\d{3})-(\d{3})-(\d{4})/).flatten #=> ["555", "333", "7777"]

是否可以将其变成这样的

{:area => "555", :city => "333", :local => "7777" }

[["555","area"], [...]]

我试过

"555-333-7777".scan(/((?<area>)\d{3})-(\d{3})-(\d{4})/).flatten

但它返回

[]

4 个答案:

答案 0 :(得分:80)

您应该match使用已命名的捕获,而不是scan

m = "555-333-7777".match(/(?<area>\d{3})-(?<city>\d{3})-(?<number>\d{4})/)
m # => #<MatchData "555-333-7777" area:"555" city:"333" number:"7777">
m[:area] # => "555"
m[:city] # => "333"

如果你想要一个实际的哈希,你可以使用这样的东西:

m.names.zip(m.captures).to_h # => {"area"=>"555", "city"=>"333", "number"=>"7777"}

或者这个(红宝石2.4或更高版本)

m.named_captures # => {"area"=>"555", "city"=>"333", "number"=>"7777"}

答案 1 :(得分:6)

这样的东西?

"555-333-7777" =~ /^(?<area>\d+)\-(?<city>\d+)\-(?<local>\d+)$/
Hash[$~.names.collect{|x| [x.to_sym, $~[x]]}]
 => {:area=>"555", :city=>"333", :local=>"7777"}

奖金版本:

Hash[[:area, :city, :local].zip("555-333-7777".split("-"))]
=> {:area=>"555", :city=>"333", :local=>"7777"}

答案 2 :(得分:0)

将捕获组名称及其值转换为哈希的方法是使用带有(?<capture_name>命名捕获的正则表达式,然后访问%~全局&#34;最后一个匹配&#34;变量

regex_with_named_capture_groups = %r'(?<area>\d{3})-(?<city>\d{3})-(?<local>\d{4})'
"555-333-7777"[regex_with_named_capture_groups]

match_hash = $~.names.inject({}){|mem, capture| mem[capture] = $~[capture]; mem}
# => {"area"=>"555", "city"=>"333", "local"=>"7777"}

# If ActiveSupport is available
match_hash.symbolize_keys!
# => {area: "555", city: "333", local: "7777"}

答案 3 :(得分:0)

如果你真的不需要散列,而只需要局部变量:

if /(?<area>\d{3})-(?<city>\d{3})-(?<number>\d{4})/ =~ "555-333-7777"
  puts area
  puts city
  puts number
end

它是如何工作的?

  • 您需要使用 =~ 正则表达式运算符。
  • 正则表达式(遗憾的是)需要在左边。如果您使用 string =~ regex,它不起作用。
  • 否则,它的语法 ?<var>named_captures 相同。
  • Ruby 1.9.3 支持它!

Official documentation:

<块引用>

当命名捕获组与文字正则表达式一起使用时 表达式的左侧和 =~ 运算符,捕获的文本 也分配给具有相应名称的局部变量。