Ruby CSV解析带有转义引号的字符串

And*_*rew 15 ruby csv

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

173,"Yukihiro \"The Ruby Guy\" Matsumoto","Japan"
Run Code Online (Sandbox Code Playgroud)

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

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

我收到此错误:

.../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)
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个错误?

joe*_*son 25

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

要解析它:

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

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

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

gsub(/(?<!\\)\\"/,'""')
Run Code Online (Sandbox Code Playgroud)


the*_*Man 17

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

不幸的是,转换器在分割成字段之后会启动转换器,并且在此步骤中,CSV对嵌入式引号感到生气,因此我们必须在"行读取"步骤和"将行解析为字段"之间进行操作" 步.

这是我的示例CSV文件:

ID,Name,Country
173,"Yukihiro \"The Ruby Guy\" Matsumoto","Japan"
Run Code Online (Sandbox Code Playgroud)

保留你的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
Run Code Online (Sandbox Code Playgroud)

以及生成的哈希和名称值:

{:ID=>"173", :Name=>"Yukihiro \"The Ruby Guy\" Matsumoto", :Country=>"Japan"}
Yukihiro "The Ruby Guy" Matsumoto
Run Code Online (Sandbox Code Playgroud)

我假设你想要一个哈希回来,因为你指定了:headers标志:

CSV.foreach('my.csv', headers: true, header_converters: :symbol) do |row|
Run Code Online (Sandbox Code Playgroud)