17

我的 CSV 文件中有一行包含一些转义引号:

173,"Yukihiro \"The Ruby Guy\" Matsumoto","Japan"

当我尝试解析它时,Ruby CSV 解析器:

require 'csv'
CSV.foreach('my.csv', headers: true, header_converters: :symbol) do |row|
  puts row
end

我收到此错误:

.../1.9.3-p327/lib/ruby/1.9.1/csv.rb:1914:in `block (2 levels) in shift': Missing or stray quote in line 122 (CSV::MalformedCSVError)

我怎样才能绕过这个错误?

4

3 回答 3

27

\"是典型的 Unix 而 Ruby CSV 期望""

解析它:

require 'csv'
text = File.read('test.csv').gsub(/\\"/,'""')
CSV.parse(text, headers: true, header_converters: :symbol) do |row|
  puts row
end

注意:如果您的 CSV 文件非常大,它会使用大量 RAM 来读取整个文件。考虑一次读取一行文件。

注意:如果您的 CSV 文件可能在斜杠前面有斜杠,请使用以下 Andrew Grimm 的建议来帮助:

gsub(/(?<!\\)\\"/,'""')
于 2013-01-26T06:50:19.483 回答
17

CSV 支持“转换器”,我们通常可以使用它来处理字段的内容,然后再将其传递回我们的代码。例如,这可用于去除一行中所有字段上的额外空格。

不幸的是,转换器在将行拆分为字段后触发,并且在该步骤中 CSV 对嵌入的引号感到生气,因此我们必须在“行读取”步骤和“将行解析为字段”之间“ 步。

这是我的示例 CSV 文件:

ID,Name,Country
173,"Yukihiro \"The Ruby Guy\" Matsumoto","Japan"

保留您的CSV.foreach方法,这是我在不让 CSV 发疯的情况下解析它的示例代码:

require 'csv'
require 'pp'

header = []
File.foreach('test.csv') do |csv_line|

  row = CSV.parse(csv_line.gsub('\"', '""')).first

  if header.empty?
    header = row.map(&:to_sym)
    next
  end

  row = Hash[header.zip(row)]
  pp row
  puts row[:Name]

end

以及由此产生的哈希值和名称值:

{:ID=>"173", :Name=>"Yukihiro \"The Ruby Guy\" Matsumoto", :Country=>"Japan"}
Yukihiro "The Ruby Guy" Matsumoto

我假设您想要一个哈希值,因为您指定了:headers标志:

CSV.foreach('my.csv', headers: true, header_converters: :symbol) do |row|
于 2013-01-26T18:28:19.957 回答
-10

在 MSExcel 中打开文件并保存为 MS-DOS 逗号分隔 (.csv)

于 2016-01-12T03:19:49.067 回答