You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

适配含空值CSV的Lua匹配模式及数组转换方案问询

解决Lua解析含空值CSV的问题

你的原代码使用[^,]+作为匹配模式,这个模式只会匹配非逗号的连续字符,遇到连续逗号(对应空值)时会直接跳过,导致解析出的列数缺失——比如示例中Refund,,10.00会被解析成Refund和10.00两个字段,漏掉中间的空值列。

下面提供两种可行的解决思路:

思路1:改进正则匹配模式

通过调整匹配模式,让它能捕获空值(包括连续逗号之间的空字符串、行首/行尾的空字段)。可以使用(.-)(,|$)的模式,同时在每行末尾额外添加一个逗号,统一处理最后一个字段的边界:

local csvfilename = "/mnt/nas/Fireflyiii.csv"

local function create_array_from_file(csvfilename)
    local file = assert(io.open(csvfilename, "r"))
    local arr = {}
    for line in file:lines() do
        local row = {}
        -- 末尾加逗号,确保最后一个字段也能被捕获
        for field in string.gmatch(line .. ",", "(.-),") do
            table.insert(row, field)
        end
        table.insert(arr, row)
    end
    return arr
end

这种方法简洁高效,但缺点是无法处理字段内包含逗号的场景(比如带引号包裹的"Doe, John"),如果你的CSV没有这类复杂字段,这个方案足够用。

思路2:手动分割字符串(更灵活)

通过遍历字符串中逗号的位置,手动提取每个字段,这种方式可以灵活处理空值,还能扩展支持带引号的复杂字段:

local csvfilename = "/mnt/nas/Fireflyiii.csv"

local function split_csv_line(line)
    local row = {}
    local start = 1
    local len = #line
    
    while start <= len do
        local comma_pos = string.find(line, ",", start)
        if not comma_pos then
            -- 处理最后一个字段
            table.insert(row, string.sub(line, start))
            break
        end
        -- 提取当前字段(包括空值,比如连续逗号时start == comma_pos,sub结果为空字符串)
        table.insert(row, string.sub(line, start, comma_pos - 1))
        start = comma_pos + 1
    end
    
    -- 如果行尾是逗号,补充最后一个空字段
    if string.sub(line, -1) == "," then
        table.insert(row, "")
    end
    
    return row
end

local function create_array_from_file(csvfilename)
    local file = assert(io.open(csvfilename, "r"))
    local arr = {}
    for line in file:lines() do
        local row = split_csv_line(line)
        table.insert(arr, row)
    end
    return arr
end

如果你的CSV存在带引号且包含逗号的字段,可以进一步扩展split_csv_line函数,判断字段是否以引号开头,然后找到对应的结束引号再分割:

local function split_csv_line(line)
    local row = {}
    local start = 1
    local len = #line
    
    while start <= len do
        local char = string.sub(line, start, start)
        -- 处理带双引号包裹的字段(可修改为单引号适配你的场景)
        if char == '"' then
            local end_quote = string.find(line, '"', start + 1)
            if not end_quote then
                -- 未找到结束引号,将剩余内容作为字段
                table.insert(row, string.sub(line, start))
                break
            end
            -- 提取引号内的内容
            table.insert(row, string.sub(line, start + 1, end_quote - 1))
            -- 跳过结束引号和后面的逗号
            start = end_quote + 1
            if start <= len and string.sub(line, start, start) == "," then
                start = start + 1
            end
        else
            local comma_pos = string.find(line, ",", start)
            if not comma_pos then
                table.insert(row, string.sub(line, start))
                break
            end
            table.insert(row, string.sub(line, start, comma_pos - 1))
            start = comma_pos + 1
        end
    end
    
    if string.sub(line, -1) == "," then
        table.insert(row, "")
    end
    
    return row
end

这个方案能覆盖绝大多数CSV场景,包括空值、带逗号的字段等。

内容的提问来源于stack exchange,提问作者nodecentral

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:05:59