【问题标题】:ruby regular expression to parse JSON fragmentruby 正则表达式解析 JSON 片段
【发布时间】:2013-10-18 23:10:52
【问题描述】:

我有一个 JSON 片段需要解析:

fragment = "\"product name\":\"12 oz. Coke\", \"more keys\":\"another value\""

我想从给定键名的任何键中获取值。

我试过了:

fragment.match/\"product name\"\:\"(.+)\"/

但我得到未终止的字符串遇到文件结尾。

你能帮我抓住字符串12 oz. Coke吗?

【问题讨论】:

  • 你不能用{}包围片段并使用JSON解析器吗?
  • 不,因为它的格式不正确,抱歉我应该澄清一下。
  • 好的,如果它的格式不正确,那么我们需要确切知道它的格式不正确,因为这将直接影响正则表达式的构造(假设正则表达式是正确的方法,那么)。

标签: ruby regex


【解决方案1】:

您不需要在正则表达式中转义引号,此外,添加一个 ? 标记以使搜索变得懒惰。这对我有用:

fragment = "\"product name\":\"12 oz. Coke\", \"more keys\":\"another value\""

p fragment[/"more keys":"(.+?)"/, 1] # => "another value"
p fragment[/"product name":"(.+?)"/, 1] # => "12 oz. Coke"

编辑:

另一种方法是将数据放入哈希中:

p Hash[fragment.gsub('"','').split(',').map{|x|x.strip.split(':')}]
# => {"product name"=>"12 oz. Coke", "more keys"=>"another value"}

【讨论】:

    【解决方案2】:

    您可以在“键值”模式中捕获“值”部分:

    str = %q("product name":"12 oz. Coke", "more keys":"another value")
    str.scan /".+?":"(.+?)"/
    => [["12 oz. Coke"], ["another value"]]
    

    http://rubular.com/r/Add4Ftf4cJ

    【讨论】:

      【解决方案3】:

      将字符串插入到有效的 JSON 中

      您可以使用JSON#parse 和一些插值将您的字符串转换为普通的Ruby Hash 对象。哈希将公开各种有用的实用方法来获取您的数据。例如:

      # use interpolation to convert to valid JSON, then parse to Hash
      fragment = "\"product name\":\"12 oz. Coke\", \"more keys\":\"another value\""
      hash = JSON.parse '{%s}' % fragment
      #=> {"product name"=>"12 oz. Coke", "more keys"=>"another value"}
      
      # manipulate your new Hash object
      hash['product name']
      #=> "12 oz. Coke"
      hash.keys
      #=> ["product name", "more keys"]
      hash.values
      #=> ["12 oz. Coke", "another value"]
      

      【讨论】:

        【解决方案4】:

        我不确定 JSON 的所有格式,但一种方法是

        Match the key name  -- probably best to set case insensitive
        Match the separator characters
        Match anything that is not a termination character into a capturing group:
        
        /product name[\\": ]+([^\\]+)/i
        

        使用您的方法的另一种方法是使捕获组变得懒惰。还要记住,在 Ruby 中,您需要使用 \\ 而不是 \。所以:

        /"\\"product name\\":\\"(.+?)\\/i
        

        根据您的数据,您可能还需要打开“点匹配换行符”

        /"\\"product name\\":\\"(.+?)\\/mi
        

        【讨论】:

        • 谢谢,但第一个解决方案是唯一匹配任何内容的解决方案,并在开始命中后捕获所有内容(它捕获“更多键..”部分):fragment.match(/product name[ \\": ]+([^\]+)/i)[1] => "12 盎司。可乐\", \"更多键\":\"另一个值\""
        • 使用我提供的任何一种变体,我看不到它会将“12 盎司可乐”以外的任何东西都捕获到第 1 组中。您在此处提供的内容与您的“真实”的环境。
        • 在这个 Ruby 正则表达式在线测试器上:regexplanet.com/advanced/ruby/index.html 使用字符串:"\"产品名称\":\"12 盎司。 Coke\", \"more keys\":\"another value\"" 和正则表达式:产品名称[\\": ]+([^\]+),结果显示捕获组 1 中有 12 盎司可乐
        • 1.9.3-p448 :001 > 片段 = "\"产品名称\":\"12 盎司。可乐\", \"更多键\":\"另一个值\"" => "\"产品名称\":\"12 oz.可乐\", \"更多键\":\"另一个值\"" 1.9.3-p448 :002 > fragment.match(/产品名称[\\": ]+([^\]+)/i) [0] => "产品名称\":\"12 盎司。可乐\", \"更多键\":\"另一个值\""
        • 如果您在“fragment.match”之前的评论部分代表您要解析的内容,那么我提供的正则表达式与这两个 12 oz 匹配。行中的可乐条目(在每场比赛的第 1 组中);在我的测试仪和我上面提到的 regexplanet 测试仪上。那位测试人员似乎不理解 /i,所以我只使用了不带修饰符的正则表达式
        【解决方案5】:

        只是为了演示如何使用内置的 JSON 解析器执行此操作(如果可以的话):

        require 'json'
        fragment = '"product name":"12 oz. Coke", "more keys":"another value"'
        hash = JSON.parse('{' + fragment + '}')
        hash['product name'] # => "12 oz. Coke"
        

        【讨论】:

          猜你喜欢
          • 2012-10-17
          • 2013-11-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多