Rails Rake Task Как парсить CSV с запятыми в полях

У меня есть csv, который содержит числа с плавающей запятой с запятыми, кроме точек, таких как «34,21», и мне нужно проанализировать его в моей задаче rake, я уже пробовал некоторые решения, подобные этому: Ruby on Rails — импорт данных из файла CSV

Но ни один из них, похоже, не работает должным образом, они просто анализируют его как 2 поля (32 и 21). Есть ли способ исправить это с помощью встроенного CSV?

Я уже пробовал это:

task :drugimport, [:filename, :model] => :environment do |task,args|
    CSV.foreach(args[:filename], { encoding: "UTF-8", headers: true, header_converters: :symbol,
        converters: :all}) do |row|
            Moulding.create!(row.to_hash)
        end
end

И этот:

require 'smarter_csv'
options = {}
SmarterCSV.process('input_file.csv', options} do |chunk|
   chunk.each do |data_hash|
       Moulding.create!( data_hash )
   end
end

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

вот мои строки, извините, есть русский, но что угодно: http://pastebin.com/RbC4SVzz ничего в нем не менял, поэтому вставил в pastebin, думаю будет полезнее, чем здесь

вот мой журнал импорта: http://pastebin.com/rzC0h9rS


person animekun    schedule 02.08.2015    source источник
comment
Вот идея... Возьмите свои строки csv и замените запятые точками, а после того, как вы проанализируете их, отмените изменение. "foo,bar,foo,baz,foo,bar".gsub(",", ".")   -  person Timur Mamedov    schedule 02.08.2015
comment
@TimKos спасибо за ответ, но я думаю, что это не правильное решение, потому что мне нужно вручную определить открытые\закрытые кавычки и найти в них запятые, а затем заменить, я думаю, есть встроенное решение, более элегантное и простое , в php довольно легко разобрать такие файлы, я думаю, у рельсов тоже есть решение   -  person animekun    schedule 02.08.2015
comment
В таком случае не могли бы вы обновить свой ответ кодом, который вы используете для анализа файлов CSV? Хотя я согласен с вами по поводу отсутствия элегантности в предыдущем решении, я думаю, что с Rails неизбежно потребуется какая-то форма регулярного выражения. Но давайте сначала посмотрим   -  person Timur Mamedov    schedule 02.08.2015
comment
@TimKos да, конечно, проверяйте обновления   -  person animekun    schedule 02.08.2015
comment
Было бы здорово увидеть, как выглядит пара строк вашего CSV.   -  person Mark Swardstrom    schedule 02.08.2015
comment
@Swards да, извините, я добавил   -  person animekun    schedule 02.08.2015


Ответы (2)


Итак, из того, что я вижу, вы, как вы сами понимаете, не передаете парсеру никаких параметров. Если не указать row_sep или любую другую форму параметра, smarter_csv будет использовать системный разделитель новой строки, который равен "\r\n" для компьютеров с Windows и "\r" для компьютеров с unix.

При этом попробуйте следующее...

require 'smarter_csv'
SmarterCSV.process('input_file.csv', :row_sep => :auto, :row_sep => ","} do |chunk|
  chunk.each do |data_hash|
    Moulding.create!( data_hash )
  end
end

Я согласен со Свардсом. То, что я сделал, предполагает довольно много вещей. Взгляд на некоторые данные CSV может быть полезен.

person Timur Mamedov    schedule 02.08.2015
comment
да, вы правы насчет \r\n, но он по-прежнему использует \r\n в качестве разделителей: c - person animekun; 02.08.2015
comment
Хм, попробуйте добавить row_sep: :auto в опции. Я обновлю свой ответ соответственно, чтобы вы могли видеть - person Timur Mamedov; 02.08.2015
comment
Я добавил несколько строк из csv с заголовками, надеюсь, это поможет. - person animekun; 02.08.2015
comment
неа, не помогло( добавил лог импорта данных, можно посмотреть где не получается импорт данных, в датах и ​​нумерациях и в ценах тоже через запятую - person animekun; 02.08.2015
comment
ну, вы будете смеяться, но ваш код и мой в теме - работает, это я, идиот, работал 20 часов, и совершенно не в своем уме, я делал изменения кода в своем локальном репо, но синтаксический анализ был делал на сервере через терминал, и я не заметил, что код на сервере не изменился, я думал это мой локальный терминал и я понял это только после того, как вздремнул :D ну извините, ребята, вы все молодцы , большое спасибо всем вам! - person animekun; 02.08.2015
comment
:0 Ах, какое облегчение! Я счастлив, что все прошло хорошо. - person Timur Mamedov; 02.08.2015

На мой взгляд, у вас есть три возможных пути, по которым вы могли бы пойти:

1) работать с "плохим" вводом и пытаться найти обходной путь

Вы можете попробовать работать построчно и попробовать

line.split (" ,")

что предполагает наличие пробела перед запятой. Другим подходом может быть идентификация числовых значений с помощью регулярного выражения и замена символа запятой (это может быть проще исправить в исходных данных!)

2) попробуйте экспортировать CSV с другим разделителем

Это зависит от того, откуда поступают данные. Если вы можете повторно экспортировать данные, возможно, это самое простое решение. В этом случае, конечно, ваши данные технически больше не будут CSV, а, например, SSV (значения, разделенные точкой с запятой).

3) попробуйте другие парсеры CSV

Я определенно могу предложить вам взглянуть на другие парсеры CSV, такие как fasterCSV и другие (см. список парсеров CSV на ruby-toolbox)

Я надеюсь, что это полезный совет — примеры данных CSV определенно помогут вам.

person Nanofunk    schedule 02.08.2015