How to do named capture in ruby

前端 未结 3 1276
無奈伤痛
無奈伤痛 2021-02-04 23:28

I want to name the capture of string that I get from scan. How to do it?

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


        
相关标签:
3条回答
  • 2021-02-05 00:29

    You should use match with named captures, not 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"
    

    If you want an actual hash, you can use something like this:

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

    Or this (ruby 2.4 or later)

    m.named_captures # => {"area"=>"555", "city"=>"333", "number"=>"7777"}
    
    0 讨论(0)
  • 2021-02-05 00:30

    Something like this?

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

    Bonus version:

    Hash[[:area, :city, :local].zip("555-333-7777".split("-"))]
    => {:area=>"555", :city=>"333", :local=>"7777"}
    
    0 讨论(0)
  • 2021-02-05 00:32

    A way to turn capture group names and their values into a hash is to use a regex with named captures using (?<capture_name> and then access the %~ global "last match" variable.

    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"}
    
    0 讨论(0)
提交回复
热议问题