Ruby通过字符串解析

问题描述:

我有一个如下所示的字符串,我必须删除第一个括号和最后一个括号之间的所有内容。所有投注都是关闭的,关于其中的内容(关于其他括号)。什么是最好的方法,谢谢。Ruby通过字符串解析

'[ 

     { "foo": 
      {"bar":"foo", 
       "bar": { 
        ["foo":"bar", "foo":"bar"] 
       } 
      } 
     } 

    ], 

"foo":"bar","foo":"bar"' 

结果:

', 

    "foo":"bar","foo":"bar"' 
+0

您的示例数据似乎不是有效的JSON。它应该是?偏差是: - 最内层的数组使用对,所以它应该是一个对象。AND最外层的范围似乎是一个列表,但它包含[]和对“”:“”..所以它不是一个对象身体或阵列身体。 - 这是你的意图吗? –

如果数据确实像她那样,你不会在年底有位的支架则:

s.gsub(/\[.*\]/m, '') 

如果你想要多一点偏执狂,那么你可以看看],后面跟着一个行尾:

s.gsub(/\[.*\],$/m, ',') 

很难说没有数据格式的规格。

+0

不错,观察得很好,实际上最后一点可能有括号。我必须找到第一个开放括号的相应的括号,并删除它们之间的内容。顺便说一句,这是JSON,但我不能把它当作哈希,因为顺序很重要。总疼痛。所以,这几乎可行,但如果我在最后有括号,该怎么办?谢谢! – dt1000

+0

@ dt1000:但是你发布的问题不是JSON。您可能想用真实数据(或至少有效的假数据)更新您的问题。我认为修复JSON生产者产生明智的JSON(即,有序的东西在数组中)是不可能的? –

+0

@ dt1000:另外,您究竟如何确定要删除的部分? –

在这里你去:

string.gsub(/\[.*\]/m, '') 

您需要使用的M标记的。匹配换行符。 。*已经是贪婪的了,所以它会匹配任意数量的括号。

很难说出你想要达到的目标,但是对我来说这看起来像JSON,因此解析它然后以这种方式操纵它可能会容易得多。

+0

不能保持秩序。不能改变json。 – dt1000

你需要多行模式:

str.gsub(/\[.*\]/m, '') 

您可以使用类似Parslet写一个解析器。 这是我写的一个例子,基于从http://www.json.org/

require 'parslet' 

#This needs a few more 'as' calls to annotate the output 
class JSONParser < Parslet::Parser 
    rule(:space)    { match('[\s\n]').repeat(1)} 
    rule(:space?)    { space.maybe } 
    rule(:digit)    { match('[0-9]') } 
    rule(:hexdigit)   { match('[0-9a-fA-F]') } 

    rule(:number)    { space? >> str('-').maybe >> 
           (str('0') | (match('[1-9]') >> digit.repeat)) >> 
           (str('.') >> digit.repeat).maybe >> 
           ((str('e')| str('E')) >> (str('+')|str('-')).maybe >> digit.repeat).maybe } 

    rule(:escaped_character) { str('\\') >> (match('["\\\\/bfnrt]') | (str('u') >> hexdigit.repeat(4,4))) } 
    rule(:string)    { space? >> str('"') >> (match('[^\"\\\\]') | escaped_character).repeat >> str('"') } 
    rule(:value)    { space? >> (string | number | object | array | str('true') | str('false') | str('null')) } 

    rule(:pair)    { string >> str(":") >> value } 
    rule(:pair_list)   { pair >> (space? >> str(',') >> pair).repeat } 
    rule(:object)    { str('{') >> space? >> pair_list.maybe >> space? >> str('}') } 

    rule(:value_list)   { value >> (space? >> str(',') >> value).repeat } 
    rule(:array)    { space? >> str('[') >> space? >> value_list.maybe >> space? >> str(']') >> space?} 

    rule(:json)    { value.as('value') >> (space? >> str(',') >> value.as('value')).repeat } 
    root(:json) 
end 

# I've changed your doc to be a list of JSON values 
doc = '[ 

     { "foo": 
      {"bar":"foo", 
       "bar": [ 
        {"foo":"bar", "foo":"bar"} 
       ] 
      } 
     } 

    ], 

{"foo":"bar"},{"foo":"bar"}' 

puts JSONParser.new.parse(doc)[1..-1].map{|value| value["value"]}.join(",") 
# => {"foo":"bar"},{"foo":"bar"} 

然而,JSON语法为您的文档是无效的JSON(据我所知)..然后你可以改变上面...

require 'parslet' 

class YourFileParser < Parslet::Parser 
    rule(:space)    { match('[\s\n]').repeat(1)} 
    rule(:space?)    { space.maybe } 
    rule(:digit)    { match('[0-9]') } 
    rule(:hexdigit)   { match('[0-9a-fA-F]') } 

    rule(:number)    { space? >> str('-').maybe >> 
           (str('0') | (match('[1-9]') >> digit.repeat)) >> 
           (str('.') >> digit.repeat).maybe >> 
           ((str('e')| str('E')) >> (str('+')|str('-')).maybe >> digit.repeat).maybe } 

    rule(:escaped_character) { str('\\') >> (match('["\\\\/bfnrt]') | (str('u') >> hexdigit.repeat(4,4))) } 
    rule(:string)    { space? >> str('"') >> (match('[^\"\\\\]') | escaped_character).repeat >> str('"') } 
    rule(:value)    { space? >> (string | number | object | array | str('true') | str('false') | str('null')) } 

    rule(:pair)    { string >> str(":") >> value } 
    rule(:pair_list)   { (pair|value) >> (space? >> str(',') >> (pair|value)).repeat } 
    rule(:object)    { str('{') >> space? >> pair_list.maybe >> space? >> str('}') } 

    rule(:value_list)   { (pair|value) >> (space? >> str(',') >> (pair|value)).repeat } 
    rule(:array)    { space? >> str('[') >> space? >> value_list.maybe >> space? >> str(']') >> space?} 

    rule(:yourdoc)   { (pair|value).as('value') >> (space? >> str(',') >> (pair|value).as('value')).repeat } 
    root(:yourdoc) 
end 

doc = '[ 

     { "foo": 
      {"bar":"foo", 
       "bar": { 
        ["foo":"bar", "foo":"bar"] 
       } 
      } 
     } 

    ], 

"foo":"bar","foo":"bar"' 

puts YourFileParser.new.parse(doc)[1..-1].map{|value| value["value"]}.join(",")