【问题标题】:Ruby String#scan equivalent to return MatchDataRuby String#scan 等价于返回 MatchData
【发布时间】:2012-03-02 04:34:49
【问题描述】:

正如问题标题中所说的那样,是否有一种 Ruby 字符串上的方法等效于 String#Scan,但它不只返回每个匹配项的列表,而是返回一个 MatchDatas 的数组?例如:

# Matches a set of characters between underscore pairs
"foo _bar_ _baz_ hashbang".some_method(/_[^_]+_/) #=> [#&ltMatchData "_bar_"&rt, &ltMatchData "_baz_"&rt]

或者我可以得到相同或相似结果的任何方式都会很好。我想这样做是为了在 Ruby 字符串中找到“字符串”的位置和范围,例如"goodbye"world" 在“'再见'残酷的'世界'”中。

【问题讨论】:

    标签: ruby regex string parsing pattern-matching


    【解决方案1】:
    memo = []
    "foo _bar_ _baz_ hashbang".scan(/_[^_]+_/) { memo << Regexp.last_match }
     => "foo _bar_ _baz_ hashbang"
    memo
     => [#<MatchData "_bar_">, #<MatchData "_baz_">]
    

    【讨论】:

    • +1 非常简洁。而Regexp.last_match 是线程本地的,所以你不会遇到竞争条件。
    【解决方案2】:

    您可以通过利用MatchData#endString#matchpos 参数轻松构建自己的。像这样的:

    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
    

    然后:

    >> 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", /_[^_]+_/)
    => []
    

    如果你真的想的话,你可以把它修补成 String。

    【讨论】:

    • 太棒了,这正是我需要的!哈,我在想我怎么能做这样的事情,但我不知道 pos 参数:)
    【解决方案3】:

    如果您不需要找回MatchDatas,这里有一种使用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_"}]
    

    【讨论】:

      猜你喜欢
      • 2012-12-03
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-03
      相关资源
      最近更新 更多