2014-10-16 47 views
1
#!/usr/bin/env ruby 
require 'rubygems' 
require 'json' 
require 'csv' 
def is_int(str) 
return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/) 
end 

lines = CSV.open(ARGV[0],{:col_sep => "\|"}).readlines 
keys = lines.delete lines.first 

File.open(ARGV[1], "w") do |f| 
data = lines.map do |values| 
is_int(values) ? values.to_i : values.to_s 
Hash[keys.zip(values)] 
end 
f.puts JSON.pretty_generate(data) 
end 

我有用于解析csv文件并以JSON格式打印第二个文件的Ruby脚本。用于将CSV转换为JSON的Ruby脚本

林用Ruby不是很好,但我还想修改为
- 读取CSV文件
- 任何线路(节选第一是头)
- 创建一个file.json其中该文件的名称是线

。例如第二个字段:
csv文件:

ID|NAME|SURNAME|TELEPHONE 
01|Jhon|Smith|123456 
02|Steve|Brown|654321 

文件jhon.json的输出:

[ 
    { 
    "ID": "01", 
    "NAME": "Jhon", 
    "SURNAME": "Smith", 
    "TELEPHONE": "123456", 
    }, 
] 

有人能帮助我吗?

+0

这里是理解CSV [阅读和解析](http://www.sitepoint.com/guide-ruby-csv-library-part)的好起点。 – 2014-10-16 10:43:26

+2

CSV库具有内置的[转换器](http://ruby-doc.org/stdlib-2.1.3/libdoc/csv/rdoc/CSV.html#Converters)。 – Stefan 2014-10-16 11:29:47

回答

1

你是接近的解决方案,但让我们重新一点点,把它简化

lines = CSV.open(ARGV[0],{:col_sep => "\|"}).readlines 
# remove first entry of the lines array 
keys = lines.shift 

lines.each do |values| 
    # convert the line into a hash and transform string into int 
    hash=Hash[keys.zip(values.map{|val| is_int(val) ? val.to_i : val}) ] 

    # Write a file with the hash results 
    File.open("#{hash['NAME']}.json", "w") do |f| 
     f.write JSON.pretty_generate [hash] 
    end 
end 

在这里,您将打开一个新的文件的每一行要保存

+0

非常感谢tomsoft! – 2014-10-16 11:36:28

+1

将块传递给'File.open'时,您不必显式关闭文件。 – Stefan 2014-10-16 11:53:06

+0

写,我正在删除它 – tomsoft 2014-10-16 13:34:13

0

tomsoft的解决方案看起来更好,但这里是我反正:

output = [] 
lines = CSV.open(ARGV[0],{:col_sep => "\|"}).readlines 
headers = lines.shift 
lines.each_with_index.map do |line, index| 
    output << Hash[*line.each_with_index.map {|col, index| [headers[index],is_int(col) ? col.to_i : col]}.flatten] 
end 
File.open(ARGV[1], "w") do |f| 
    f << output 
end 
+0

感谢阿里为我们的贡献! – 2014-10-16 11:37:02

2

的CSV库可以处理大部分的处理给你:

require 'csv' 
require 'json' 

options = { col_sep: '|', converters: :numeric, headers: true } 

CSV.foreach(ARGV[0], options) do |row| 
    filename = "#{row['NAME'].downcase}.json" 
    File.open(filename, 'w') { |f| f << JSON.pretty_generate(row.to_hash) } 
end 

通过converters: :numeric将数字字段转换为数字类型(IntegerFloat)。

headers: true选项允许您按名称(例如row['NAME'])访问字段并将行转换为散列。

+0

辉煌的解决方案,谢谢! – 2014-10-16 11:52:01

+0

太棒了,我甚至都不知道这些选项,谢谢 – tomsoft 2014-10-16 13:37:16