Ruby String#scan equivalent to return MatchData

后端 未结 3 1055
余生分开走
余生分开走 2021-02-08 03:18

As basically stated in the question title, is there a method on Ruby strings that is the equivalent to String#Scan but instead of returning just a list of each match, it would r

相关标签:
3条回答
  • 2021-02-08 03:28

    You could easily build your own by exploiting MatchData#end and the pos parameter of String#match. Something like this:

    def matches(s, re)
      start_at = 0
      matches  = [ ]
      while(m = s.match(re, start_at))
        matches.push(m)
        start_at = m.end(0)
      end
      matches
    end
    

    And then:

    >> matches("foo _bar_ _baz_ hashbang", /_[^_]+_/)
    => [#<MatchData "_bar_">, #<MatchData "_baz_">]
    >> matches("_a_b_c_", /_[^_]+_/)
    => [#<MatchData "_a_">, #<MatchData "_c_">]
    >> matches("_a_b_c_", /_([^_]+)_/)
    => [#<MatchData "_a_" 1:"a">, #<MatchData "_c_" 1:"c">]
    >> matches("pancakes", /_[^_]+_/)
    => []
    

    You could monkey patch that into String if you really wanted to.

    0 讨论(0)
  • 2021-02-08 03:41
    memo = []
    "foo _bar_ _baz_ hashbang".scan(/_[^_]+_/) { memo << Regexp.last_match }
     => "foo _bar_ _baz_ hashbang"
    memo
     => [#<MatchData "_bar_">, #<MatchData "_baz_">]
    
    0 讨论(0)
  • 2021-02-08 03:43

    If you don't need to get MatchDatas back, here's a way using StringScanner.

    require 'strscan'
    
    rxp = /_[^_]+_/
    scanner = StringScanner.new "foo _barrrr_ _baz_ hashbang"
    match_infos = []
    until scanner.eos?
      scanner.scan_until rxp
      if scanner.matched?
        match_infos << {
          pos: scanner.pre_match.size,
          length: scanner.matched_size,
          match: scanner.matched
        }
      else
        break
      end
    end
    
    p match_infos
    # [{:pos=>4, :length=>8, :match=>"_barrrr_"}, {:pos=>13, :length=>5, :match=>"_baz_"}]
    
    0 讨论(0)
提交回复
热议问题