2017-01-13 7 views
0

Я использую Ruby 2.4. Как разобрать строку с разделителями табуляции, содержащую символ цитаты? Это то, что сейчас со мной происходит ...Как разобрать строку с разделителями табуляции, содержащую цитату?

2.4.0 :003 > line = "11\tDave\tO\"malley" 
=> "11\tDave\tO\"malley" 
2.4.0 :004 > CSV.parse(line, col_sep: "\t") 
CSV::MalformedCSVError: Illegal quoting in line 1. 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1912:in `block (2 levels) in shift' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1868:in `each' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1868:in `block in shift' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `loop' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `shift' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1770:in `each' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1784:in `to_a' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1784:in `read' 
    from /Users/davea/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/csv.rb:1324:in `parse' 
    from (irb):4 
    from /Users/davea/.rvm/gems/[email protected]/gems/railties-5.0.1/lib/rails/commands/console.rb:65:in `start' 
    from /Users/davea/.rvm/gems/[email protected]/gems/railties-5.0.1/lib/rails/commands/console_helper.rb:9:in `start' 
    from /Users/davea/.rvm/gems/[email protected]/gems/railties-5.0.1/lib/rails/commands/commands_tasks.rb:78:in `console' 
    from /Users/davea/.rvm/gems/[email protected]/gems/railties-5.0.1/lib/rails/commands/commands_tasks.rb:49:in `run_command!' 
    from /Users/davea/.rvm/gems/[email protected]/gems/railties-5.0.1/lib/rails/commands.rb:18:in `<top (required)>' 
    from bin/rails:4:in `require' 
    from bin/rails:4:in `<main>' 

Хотя Teh пример иллюстрирует мою точку зрения, я не могу легко контролировать вход поступает. Таким образом, хотя ответ coudl быть < «Удалить все цитаты из ТОЙ строки перед разбором: «Я хочу как можно ближе сохранить данные.

ответ

1

Это неправильный документ, если вы пытаетесь придерживаться стандарта CSV. Вместо внесения вы можете просто грубую силу и на молитве нет никаких вкладок в самих данных:

line.split(/\t/) 

разбора библиотека CSV очень удобно, когда вы имеете дело с данными, как это:

"1\t2\t\"3a\t3b\"\t4" 

Обновление: Если вы готовы к злоупотреблению библиотеки CSV мало, то вы можете сделать это:

CSV.parse("11\tDave\tO\"malley", col_sep: "\t", quote_char: "\0") 

это в основном убивает обнаружение цитаты, так что если re - другие данные, которые зависят от правильной обработки, это может не сработать.

+0

Я не хотел чтобы попасть в сорняки в моем вопросе, но у меня есть общая функция, которая на самом деле является CSV.parse (строка, col_sep: разделитель), в которой разделитель может быть запятой или вкладкой. Существуют ли другие разделители? Вы говорите, что нет способа чтобы заставить это работать с использованием метода CSV.parse? – Dave

+0

В библиотеке CSV могут обрабатываться только данные, которые соответствуют, по крайней мере, примерно стандарту CSV. Так как ваших данных нет, у вас осталось несколько неоптимальных решений Я добавил альтернативу этому ответу. – tadman

0

«11 \ tDave \ к \» Малли»не достоверные данные в формате CSV. Как ни странно, ответ заключается в использовании двух двойных кавычек, и двойные кавычки каждый элемент

2.3.1 :001 > require 'csv' 
=> true 
2.3.1 :002 > line = "\"11\"\t\"Dave\"\t\"O\"\"malley\"" 
=> "\"11\"\t\"Dave\"\t\"O\"\"malley\"" 
2.3.1 :003 > puts line # for clarity 
"11" "Dave" "O""malley" 
=> nil 
2.3.1 :004 > CSV.parse(line, col_sep: "\t") 
=> [["11", "Dave", "O\"malley"]] 
+0

См. Https://tools.ietf.org/html/rfc4180#page-3, пункт 7, для объяснения. – Glyoko