模块:Csv.lua:修订间差异
来自「荏苒之境」
页面内容被替换为“local function parse_row(input, sep, pos) local row = {} local pos = pos or 1 while true do local c = string.sub(input, pos, pos) if c == "" then break end if c == '"' then local text = '' local s, e, txt, c1 repeat s, e, txt, c1 = string.find(input, '^(.-")(.)', pos + 1) text = text..txt pos = e until c1 == sep or c1 == "\r" or c1 == "\n" table.insert(row, string.sub(text, 1, -2)) c = c1 pos = pos + 1 else local s…” 标签:替换 |
无编辑摘要 |
||
第1行: | 第1行: | ||
--[=[<%-- [PAGE_INFO] | |||
comment = #Please do not remove this struct. It's record contains some important information of edit. This struct will be removed automatically after you push edits.# | |||
pageTitle = #模块:Csv.lua# | |||
pageID = #567# | |||
revisionID = #2289# | |||
contentModel = #Scribunto# | |||
contentFormat = #text/plain# | |||
[END_PAGE_INFO] --%>--]=] | |||
--[[ | |||
CSV Library v1 (Author: Michael Lutz, 2022-12-14) | |||
Built on: http://lua-users.org/wiki/LuaCsv | |||
csv.load = function(filename, delimiter, header) | |||
filename := CSV file to load | |||
delimiter := Delimiter (";", ",", "\t", etc..), default = ',' | |||
header := (optional) if first line is a header (true/false), default = false | |||
automatically removes quotes from text | |||
returns a table | |||
csv.save = function(filename, delimiter, data, header) | |||
filename := CSV file to write to | |||
delimiter := Delimiter (";", ",", "\t", etc..), default = ',' | |||
data := a Lua table that holds the rows and columns | |||
header := a Lua table that holds the names of the columns e.g. { "Name", "Address", "Email", ... } | |||
--]] | |||
local function parse_row(input, sep, pos) | local function parse_row(input, sep, pos) | ||
local row = {} | |||
local pos = pos or 1 | |||
while true do | |||
local c = string.sub(input, pos, pos) | |||
if c == "" then break end | |||
if c == '"' then | |||
local text = '' | |||
local s, e, txt, c1 | |||
repeat | |||
s, e, txt, c1 = string.find(input, '^(.-")(.)', pos + 1) | |||
text = text..txt | |||
pos = e | |||
until c1 == sep or c1 == "\r" or c1 == "\n" | |||
table.insert(row, string.sub(text, 1, -2)) | |||
c = c1 | |||
pos = pos + 1 | |||
else | |||
local s, e, text, c1 = string.find( | |||
input, "^([^%"..sep.."\r\n]-)([%"..sep.."\r\n])", pos) | |||
pos = e+1 | |||
table.insert(row, text) | |||
c = c1 | |||
end | |||
if c == "\n" then return row, pos | |||
elseif c == "\r" then return row, pos+1 end | |||
end | |||
end | end | ||
local csv = {} | local csv = {} | ||
csv.parse = function( | csv.parse = function(str, delimiter, header) | ||
local sep = string.sub(delimiter,1,1) or ',' | |||
local pos = 1 | |||
local t_csv = {} | |||
local f_header = nil | |||
local t_header = {} | |||
if header then | |||
t_header,pos = parse_row(str, sep, pos) | |||
local head = {} | |||
for i,v in ipairs(t_header) do | |||
head[v] = i | |||
end | |||
f_header = function (t,k) | |||
local i = head[k] | |||
if i then | |||
return t[i] | |||
end | |||
return nil | |||
end | |||
end | |||
local row = {} | |||
row, pos = parse_row(str, sep, pos) | |||
while row do | |||
if header then | |||
setmetatable(row, { __index = f_header }) | |||
end | |||
table.insert(t_csv, row) | |||
row, pos = parse_row(csv, sep, pos) | |||
end | |||
return t_csv, t_header | |||
end | end | ||
local function format_csv(str, sep) | local function format_csv(str, sep) | ||
local str, matches = string.gsub(str or "", '"', '""') | |||
if (string.find(str, "[%"..sep.."\r\n]") or (matches > 0)) then | |||
return '"'..str..'"' | |||
end | |||
return str | |||
end | end | ||
csv.format = function(delimiter, data, header) | csv.format = function(delimiter, data, header) | ||
local r = {} | |||
local sep = string.sub(delimiter,1,1) or ',' | |||
if header then | |||
for i,v in ipairs(header) do | |||
r[#r+1] = format_csv(v, sep) | |||
r[#r+1] = sep | |||
end | |||
r[#r] = "\n" | |||
end | |||
for i,v in ipairs(data) do | |||
for i2,v2 in ipairs(v) do | |||
r[#r+1] = format_csv(v2, sep) | |||
r[#r+1] = sep | |||
end | |||
r[#r] = "\n" | |||
end | |||
return table.concat(r) | |||
end | end | ||
return csv | return csv |
2025年8月1日 (五) 23:13的版本
此模块的文档可以在模块:Csv.lua/doc创建
--[=[<%-- [PAGE_INFO]
comment = #Please do not remove this struct. It's record contains some important information of edit. This struct will be removed automatically after you push edits.#
pageTitle = #模块:Csv.lua#
pageID = #567#
revisionID = #2289#
contentModel = #Scribunto#
contentFormat = #text/plain#
[END_PAGE_INFO] --%>--]=]
--[[
CSV Library v1 (Author: Michael Lutz, 2022-12-14)
Built on: http://lua-users.org/wiki/LuaCsv
csv.load = function(filename, delimiter, header)
filename := CSV file to load
delimiter := Delimiter (";", ",", "\t", etc..), default = ','
header := (optional) if first line is a header (true/false), default = false
automatically removes quotes from text
returns a table
csv.save = function(filename, delimiter, data, header)
filename := CSV file to write to
delimiter := Delimiter (";", ",", "\t", etc..), default = ','
data := a Lua table that holds the rows and columns
header := a Lua table that holds the names of the columns e.g. { "Name", "Address", "Email", ... }
--]]
local function parse_row(input, sep, pos)
local row = {}
local pos = pos or 1
while true do
local c = string.sub(input, pos, pos)
if c == "" then break end
if c == '"' then
local text = ''
local s, e, txt, c1
repeat
s, e, txt, c1 = string.find(input, '^(.-")(.)', pos + 1)
text = text..txt
pos = e
until c1 == sep or c1 == "\r" or c1 == "\n"
table.insert(row, string.sub(text, 1, -2))
c = c1
pos = pos + 1
else
local s, e, text, c1 = string.find(
input, "^([^%"..sep.."\r\n]-)([%"..sep.."\r\n])", pos)
pos = e+1
table.insert(row, text)
c = c1
end
if c == "\n" then return row, pos
elseif c == "\r" then return row, pos+1 end
end
end
local csv = {}
csv.parse = function(str, delimiter, header)
local sep = string.sub(delimiter,1,1) or ','
local pos = 1
local t_csv = {}
local f_header = nil
local t_header = {}
if header then
t_header,pos = parse_row(str, sep, pos)
local head = {}
for i,v in ipairs(t_header) do
head[v] = i
end
f_header = function (t,k)
local i = head[k]
if i then
return t[i]
end
return nil
end
end
local row = {}
row, pos = parse_row(str, sep, pos)
while row do
if header then
setmetatable(row, { __index = f_header })
end
table.insert(t_csv, row)
row, pos = parse_row(csv, sep, pos)
end
return t_csv, t_header
end
local function format_csv(str, sep)
local str, matches = string.gsub(str or "", '"', '""')
if (string.find(str, "[%"..sep.."\r\n]") or (matches > 0)) then
return '"'..str..'"'
end
return str
end
csv.format = function(delimiter, data, header)
local r = {}
local sep = string.sub(delimiter,1,1) or ','
if header then
for i,v in ipairs(header) do
r[#r+1] = format_csv(v, sep)
r[#r+1] = sep
end
r[#r] = "\n"
end
for i,v in ipairs(data) do
for i2,v2 in ipairs(v) do
r[#r+1] = format_csv(v2, sep)
r[#r+1] = sep
end
r[#r] = "\n"
end
return table.concat(r)
end
return csv