65 lines
1.5 KiB
Ruby
Executable file
65 lines
1.5 KiB
Ruby
Executable file
class String
|
|
def from_csv(sep = /,/)
|
|
ret = [[]]
|
|
c = chars
|
|
quote = "\""
|
|
comma = ","
|
|
i = 0
|
|
expecting_quote = false
|
|
while i < c.length
|
|
if c[i] == quote
|
|
if ret[-1].empty? then expecting_quote = true
|
|
elsif c[i+1] == quote then i += 1; ret[-1].push(quote)
|
|
elsif expecting_quote and (c[i+1] == comma) then
|
|
ret.push([])
|
|
expecting_quote = false
|
|
i += 1
|
|
elsif expecting_quote and (c[i+1] == nil) then
|
|
expecting_quote = false
|
|
else
|
|
raise "Invalid CSV Line (misplaced quote at #{i}; #{c[i+1]}): #{self}"
|
|
end
|
|
elsif c[i] == comma
|
|
if expecting_quote
|
|
ret[-1].push(comma)
|
|
else
|
|
ret.push([])
|
|
expecting_quote = false
|
|
end
|
|
else
|
|
ret[-1].push(c[i])
|
|
end
|
|
i += 1
|
|
end
|
|
ret.map { |col| col.join}
|
|
end
|
|
end
|
|
|
|
class Array
|
|
def from_csv
|
|
self.map { |l| l.to_s.chomp.from_csv }
|
|
end
|
|
|
|
def to_csv(f)
|
|
File.open(f, "w+") { |f| each { |row| f.puts(row.join(',')) }}
|
|
end
|
|
end
|
|
|
|
class IO
|
|
def from_csv(args = {})
|
|
header = args.fetch(:header, false)
|
|
separator = args.fetch(:separator, /,/)
|
|
keys = readline.chomp.
|
|
sub(/ *$/, "").sub(/^ */,"").
|
|
from_csv(separator) if header;
|
|
map { |l| l.to_s.chomp.from_csv(separator) }.
|
|
map { |a| if header then keys.zip(a).to_h else a end }
|
|
end
|
|
end
|
|
|
|
class File
|
|
def File.csv(f, args = {})
|
|
File.open(f) {|io| io.from_csv(args) }
|
|
end
|
|
end
|