「第2回エンペディア大賞」が2月いっぱい開催中です。2024年に作成された記事の中から、お気に入りの記事に投票しましょう!
モジュール:TSV
ナビゲーションに移動
検索に移動
local p = {}
function p.toArr2D(args)
local tsv = args[1]
if tsv == nil then return {} end
local maxStep = args.maxStep or 1000 -- 最大セル解釈数
local tbl = {}
local row = {}
-- パフォーマンス最適化のため変数宣言をfor文の外に
local start = nil -- セル内容の開始idx
local stop = nil -- セル内容の終了idx
local startDQ = 0
local stopDQ = 0
local isLf = false
local isDQBegin = false
local isDQSpace = false -- ダブルクォートで囲まれたセルか否か
local cellTxt = ''
local tabPos = 0
local cursor = 1
local cursorDQ = 1
for i = 1, maxStep do -- maxStepステップ以上のループ拒否
start = nil
stop = nil
isLf = false
isDQBegin = false
isDQSpace = false
-- 開始時のダブルクォートらの塊が偶数・奇数のどちらか、判定
startDQ, stopDQ = tsv:find('^"+', cursor)
if startDQ ~= nil and startDQ == cursor then
isDQBegin = (stopDQ - startDQ + 1) % 2 == 1
end
if isDQBegin then
cursorDQ = stopDQ + 1
-- 次のタブの位置を予め把握
tabPos = tsv:find('\t', cursorDQ, true)
-- ~ 奇数個ある終了ダブルクォート塊 (タブ|改行) を検索
for j = 1, maxStep do
startDQ, stopDQ = tsv:find('"-[\t\n]', cursorDQ)
if startDQ > tabPos then break end -- タブ優先
if startDQ ~= nil and (stopDQ - startDQ) % 2 == 1 then -- マッチ
start = cursor + 1
stop = stopDQ - 2
cursor = stopDQ + 1
if tsv:sub(stopDQ, stopDQ) == '\n' then isLf = true end
isDQSpace = true
break
end
if startDQ == nil then
startDQ, stopDQ = tsv:find('"-$', cursorDQ)
if startDQ == nil then break end -- 終了塊に最後まで出会わなければbreak
if startDQ ~= nil and (stopDQ - startDQ + 1) % 2 == 1 then -- マッチ
start = cursor + 1
stop = stopDQ - 1
cursor = stopDQ + 1
isLf = true
isDQSpace = true
break
end
end
cursorDQ = stopDQ + 1
end
end
if start == nil then
-- ~ (改行|タブ) にマッチ
start, stop = tsv:find('.-[\n\t]', cursor)
if start ~= nil then
cursor = stop + 1
isLf = tsv:sub(stop, stop) == '\n'
stop = stop - 1
else -- 何にもマッチしない
start = cursor
cursor = #tsv + 1
isLf = true
stop = cursor - 1
end
end
-- セル内容を取得し、列に追加
cellTxt = tsv:sub(start, stop)
if isDQSpace then cellTxt = cellTxt:gsub('""', '"') end
table.insert(row, cellTxt)
if isLf then -- 次列へ
table.insert(tbl, row)
row = {}
end
if #tsv < cursor then break end
end
return tbl
end
return p