如何在Lua中将模糊格式行数据解析为指定结构的表格?
Lua:从格式模糊的文本中提取软件信息并整理为表格
需求是从一段无固定列索引的模糊文本中提取名称、版本、来源三类信息,整理成指定结构的Lua表。示例输入与期望输出如下:
示例输入
local update = [[Microsoft Visual C++ 2008 Redistributable - … Microsoft.VCRedist.2008.x64 9.0.30729.6161 winget Java 8 Update 391 {71324AE4-039E-4CA4-87B4-2F32180391F0} 8.0.3910.13 Update for Windows 10 for x64-based Systems … {7B63012A-4AC6-40C6-B6AF-B24A84359DD5} 8.93.0.0 Microsoft Visual C++ 2008 Redistributable - … {8220EEFE-38CD-377E-8595-13398D740ACE} 9.0.30729 GiliSoft Screen Recorder Pro {85B92051-32EF-61AA-AB7C-24B0B2DB29AC}_is1 13.0.0 Security Update for Microsoft Office 2016 (K… {90160000-0011-0000-0000-0000000FF1CE}_Offic… Unknown ]]
期望输出
local resTbl = { {"Microsoft Visual C++ 2008 Redistributable", "9.0.30729.6161","winget"}, {"Java 8 Update 391", "8.0.3910.13",""}, {"Update for Windows 10 for x64-based Systems","8.93.0.0", ""}, {"Microsoft Visual C++ 2008 Redistributable", "9.0.30729", ""}, {"GiliSoft Screen Recorder Pro", "13.0.0", ""}, {"Security Update for Microsoft Office 2016", "Unknown", ""} }
当前通过CMD输出保存为CSV、截取固定字符串区间的方法存在CMD窗口长时间显示的问题,以下是更优的纯Lua处理方案:
解决方案:纯Lua文本解析
直接在Lua内处理原始文本,无需依赖外部CMD工具,彻底解决窗口显示问题,同时适配模糊格式。
完整代码实现
-- 扩展字符串trim方法 function string.trim(s) return s:match'^%s*(.*%S)' or '' end local update = [[Microsoft Visual C++ 2008 Redistributable - … Microsoft.VCRedist.2008.x64 9.0.30729.6161 winget Java 8 Update 391 {71324AE4-039E-4CA4-87B4-2F32180391F0} 8.0.3910.13 Update for Windows 10 for x64-based Systems … {7B63012A-4AC6-40C6-B6AF-B24A84359DD5} 8.93.0.0 Microsoft Visual C++ 2008 Redistributable - … {8220EEFE-38CD-377E-8595-13398D740ACE} 9.0.30729 GiliSoft Screen Recorder Pro {85B92051-32EF-61AA-AB7C-24B0B2DB29AC}_is1 13.0.0 Security Update for Microsoft Office 2016 (K… {90160000-0011-0000-0000-0000000FF1CE}_Offic… Unknown ]] local resTbl = {} -- 逐行处理文本 for line in string.gmatch(update, "[^\n]+") do local trimmedLine = string.trim(line) if trimmedLine ~= "" then -- 1. 提取名称:匹配到第一个大括号或省略号前缀,清理冗余内容 local name = string.match(trimmedLine, "^(.-)%s*(?:%{|- …)") -- 兜底匹配:如果上面的规则不生效,匹配到版本/Unknown前的内容 if not name then name = string.match(trimmedLine, "^(.-)%s+(?:%d+%.|Unknown)") end name = name and string.gsub(name, "%s+$", "") or "" -- 2. 提取版本:匹配标准版本格式或Unknown local version = string.match(trimmedLine, "(%d+%.%d+[%d%.]*|Unknown)") or "" version = string.gsub(version, "%s+$", "") -- 3. 提取来源:匹配行尾的非版本字段 local source = string.match(trimmedLine, "%s+([%w]+)%s*$") -- 排除来源与版本/Unknown重复的情况 if source and (source == version or source == "Unknown") then source = "" else source = source or "" end -- 将提取的字段加入结果表 table.insert(resTbl, {name, version, source}) end end -- 验证输出(可选) for _, item in ipairs(resTbl) do print(string.format('{"%s", "%s", "%s"}', item[1], item[2], item[3])) end
关键逻辑说明
- 文本分割:用
string.gmatch按换行符拆分文本,过滤空行后逐行处理 - 名称提取:针对文本中名称后常跟
- …或{GUID}的特征,用正则精准匹配有效名称范围,同时做兜底处理适应特殊行 - 版本提取:匹配
x.x.x格式的版本号或Unknown关键字,确保覆盖所有情况 - 来源提取:匹配行尾的非版本字段,排除误判为来源的版本/Unknown值
优势
- 完全在Lua环境内完成,无需调用外部CMD工具,彻底解决CMD窗口长时间显示的问题
- 正则匹配适配模糊格式,比固定字符串截取更灵活,能应对文本格式的小幅度变化
内容的提问来源于stack exchange,提问作者A_CE
相关产品推荐
相关产品推荐

