temas-seminarios-borromeos/csv_fixer.lua

96 lines
2.2 KiB
Lua

local input = arg[1]
local output = arg[2]
local f = assert(io.open(input, "r"))
local s = f:read("*a")
f:close()
local delim = ","
local out, row = {}, {}
local i, n = 1, #s
local function csv_escape(cell)
local needs_quotes =
cell:find(delim, 1, true) or cell:find('"', 1, true) or
cell:find("\\ ", 1, true) or cell:find("[\r\n]", 1, true)
if needs_quotes then
cell = cell:gsub('"','""')
return '"' .. cell .. '"'
end
return cell
end
local function push_cell(cell) row[#row+1] = cell end
local function end_row() out[#out+1] = row; row = {} end
while i <= n do
local c = s:sub(i,i)
if c == '"' then
i = i + 1
local buf = {}
while i <= n do
c = s:sub(i,i)
if c == '"' then
local nextc = s:sub(i+1,i+1)
if nextc == '"' then
buf[#buf+1] = '"'
i = i + 2
else
i = i + 1
break
end
else
buf[#buf+1] = c
i = i + 1
end
end
local cell = table.concat(buf)
cell = cell:gsub("\r\n","\\\\{}")
cell = cell:gsub("\n","\\\\{}")
cell = cell:gsub("\r","\\\\{}")
push_cell(cell)
local c2 = s:sub(i,i)
if c2 == delim then i = i + 1
elseif c2 == "\n" then i = i + 1; end_row()
elseif c2 == "\r" then
if s:sub(i+1,i+1) == "\n" then i = i + 2 else i = i + 1 end
end_row()
end
else
local buf = {}
while i <= n do
c = s:sub(i,i)
if c == delim or c == "\n" or c == "\r" then break end
buf[#buf+1] = c
i = i + 1
end
local cell = table.concat(buf)
cell = cell:gsub("\r\n","\\\\{}")
cell = cell:gsub("\n","\\\\{}")
cell = cell:gsub("\r","\\\\{}")
push_cell(cell)
if i <= n and s:sub(i,i) == delim then i = i + 1
elseif i <= n and s:sub(i,i) == "\n" then i = i + 1; end_row()
elseif i <= n and s:sub(i,i) == "\r" then
if s:sub(i+1,i+1) == "\n" then i = i + 2 else i = i + 1 end
end_row()
end
end
end
if #row > 0 then end_row() end
local fo = assert(io.open(output, "w"))
for r = 1, #out do
local cells = out[r]
for k = 1, #cells do
if k > 1 then fo:write(delim) end
fo:write(csv_escape(cells[k] or ""))
end
if r < #out then fo:write("\n") end
end
fo:close()