2011-10-07 94 views
3

我有一個如下所示的字符串,我必須刪除第一個括號和最後一個括號之間的所有內容。所有投注都是關閉的,關於其中的內容(關於其他括號)。什麼是最好的方法,謝謝。Ruby通過字符串解析

'[ 

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

    ], 

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

結果:

', 

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

您的示例數據似乎不是有效的JSON。它應該是?偏差是: - 最內層的數組使用對,所以它應該是一個對象。AND最外層的範圍似乎是一個列表,但它包含[]和對「」:「」..所以它不是一個對象身體或陣列身體。 - 這是你的意圖嗎? –

回答

1

如果數據確實像她那樣,你不會在年底有位的支架則:

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

如果你想要多一點偏執狂,那麼你可以看看],後面跟着一個行尾:

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

很難說沒有數據格式的規格。

+0

不錯,觀察得很好,實際上最後一點可能有括號。我必須找到第一個開放括號的相應的括號,並刪除它們之間的內容。順便說一句,這是JSON,但我不能把它當作哈希,因爲順序很重要。總疼痛。所以,這幾乎可行,但如果我在最後有括號,該怎麼辦?謝謝! – dt1000

+0

@ dt1000:但是你發佈的問題不是JSON。您可能想用真實數據(或至少有效的假數據)更新您的問題。我認爲修復JSON生產者產生明智的JSON(即,有序的東西在數組中)是不可能的? –

+0

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

0

在這裏你去:

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

您需要使用的M標記的。匹配換行符。 。*已經是貪婪的了,所以它會匹配任意數量的括號。

0

很難說出你想要達到的目標,但是對我來說這看起來像JSON,因此解析它然後以這種方式操縱它可能會容易得多。

+0

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

0

你需要多行模式:

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

您可以使用類似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(",")