Ruby разбирает строку - PullRequest
       20

Ruby разбирает строку

3 голосов
/ 07 октября 2011

У меня есть строка, которая выглядит как показано ниже, и я должен удалить все между первой и последней скобками. Все ставки сняты, на то, что между (относительно других скобок). Что будет лучшим подходом, спасибо.

'[

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

    ],

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

результат:

  ',

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

Ответы [ 5 ]

1 голос
/ 07 октября 2011

Если ваши данные действительно выглядят так, и в конце у вас нет квадратных скобок, то:

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

Если вы хотите быть немного более параноиком, тогда вы можете поискать ], с последующим концом строки:

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

Трудно сказать больше, чем это, без указания формата данных.

0 голосов
/ 24 ноября 2011

Вы можете использовать что-то вроде Parslet для написания парсера.Вот пример, который я написал на основе грамматики JSON от 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 (насколько я знаю) ... тогда вы можете изменить вышеприведенное ...

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(",")
0 голосов
/ 07 октября 2011

вам нужен многострочный режим:

str.gsub(/\[.*\]/m, '')
0 голосов
/ 07 октября 2011

Трудно сказать, чего вы пытаетесь достичь, но для меня это выглядит как JSON, так что, вероятно, было бы намного проще разобрать его, а затем манипулировать им таким образом.

0 голосов
/ 07 октября 2011

Вот, пожалуйста:

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

Вам необходимо использовать флаг m для. чтобы соответствовать символам новой строки. . * уже жадный, поэтому он будет соответствовать любому числу скобок между ними.

...