平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“lua日志文件处理代码”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
在这个场景下,目前我找到的文件夹的搜索工具,最多能够完成把搜索到的单行的内容,进行输出出来,或者进行一些轻松的处理,但是不够灵活。
在这个场景下,所以就用lua自己写了个,能够完成自己定义搜索处理函数,进行一些数据的处理,省去了将搜索结果放到excel中再处理的过程。
-- search_log.lua
tbResult = {};
tbCmdResult = {};
local szTmpFolderPath = os.getenv("temp");
if not szTmpFolderPath then
os.execute("md c:\temp")
szTmpFolderPath = "c:\temp";
end
local tbSpecialWorld =
{
["("] = "%(", [")"] = "%)", ["."] = "%.", ["%"] = "%%",
["+"] = "%+", ["-"] = "%-", ["*"] = "%*", ["?"] = "%?",
["["] = "%[", ["]"] = "%]", ["^"] = "%^", ["$"] = "%$",
};
function FormatCmd(szCmd)
return string.gsub(szCmd, ".", function(s) return tbSpecialWorld[s] or s; end)
end
function FormatPath(szPath)
string.gsub(szPath, "[\/]$", "");
return string.gsub(szPath, "/", "\");
end
function CheckFile(szFilePath)
local file = io.open(szFilePath, "rb");
if not file then
return;
end
file:close();
return true;
end
function OpenFile(szFilePath)
if not CheckFile(szFilePath) then
return;
end
local tbFile = {};
for line in io.lines(szFilePath) do
table.insert(tbFile, line);
end
return tbFile;
end
function SearchFile(szFilePath, szCmd, fnCmd2Line, fnFileName)
local tbFile = OpenFile(szFilePath);
if not tbFile then
return;
end
tbResult[szFilePath] = tbResult[szFilePath] or {};
local szCmdResult = "";
for nLine, szLine in ipairs(tbFile) do
if string.match(szLine, szCmd) then
szCmdResult = fnCmd2Line(szLine);
if szCmdResult and szCmdResult ~= "" then
table.insert(tbCmdResult, szCmdResult);
end
table.insert(tbResult[szFilePath], nLine .. ":" .. szLine);
end
end
return 1;
end
function Cmd2Line(szLine)
return;
end
function CheckName(szFileName)
return true;
end
function SearchDir(szFolderPath, szCmd, fnCmd2Line, fnCheckName, nIdx)
if not szCmd or szCmd == "" then
return;
end
local fnCmd2Line = fnCmd2Line or Cmd2Line;
local fnCheckName = fnCheckName or CheckName;
local nIdx = nIdx or 0;
local szTmpFileName = szTmpFolderPath .. "\SearchDirTemp" .. nIdx .. ".tmp";
os.execute("dir /b ".. szFolderPath .." >" .. szTmpFileName);
local tbFile = OpenFile(szTmpFileName);
if not tbFile or #tbFile == 0 then
return;
end
local szPath = "";
for _, szFileName in ipairs(tbFile) do
szPath = szFolderPath .. "\" .. szFileName;
if not CheckFile(szPath) then
SearchDir(szPath, szCmd, fnCmd2Line, nIdx + 1);
else
if CheckName(szFileName) then
SearchFile(szPath, szCmd, fnCmd2Line);
end
end
end
end
function Write2File(szInfo, szFilePath)
local file = io.open(szFilePath, "w");
if not file then
print(szInfo);
print("Write2File ERR ?? not file " .. szFilePath);
return;
end
file:write(szInfo);
file:close();
end
function DoSearchDir(szFolderPath, szCmd, tbParam)
if not szFolderPath or szFolderPath == "" or not szCmd or szCmd == "" then
return;
end
tbParam = tbParam or {};
szFolderPath = FormatPath(szFolderPath);
if tbParam.bIsMatch then
szCmd = FormatCmd(szCmd);
end
local nTime = os.time();
SearchDir(szFolderPath, szCmd, tbParam.fnCmd2Line or Cmd2Line, tbParam.fnCheckName or CheckName, 0);
nTime = os.time() - nTime;
print("搜索用时:" .. nTime);
local szResultPath = tbParam.szResultPath or (szTmpFolderPath .. "\result.tab.tmp");
local szResult = "";
for szFilePath, tbInfo in pairs(tbResult) do
szResult = szResult .. szFilePath .. "n";
for _, szLine in pairs(tbInfo) do
szResult = szResult .. szLine .. "n";
end
end
Write2File(szResult, szResultPath);
local szCmdResult = "";
for _, szLine in pairs(tbCmdResult) do
szCmdResult = szCmdResult .. szLine .. "n";
end
Write2File(szCmdResult, tbParam.szCmdResultPath or (szTmpFolderPath .. "\cmd_result.tab.tmp"));
end
--tbParam =
--{
-- bIsMatch = false; -- 是否使用正则方式搜索
-- fnCmd2Line = function () end; -- 自定义搜索行内容处理函数
-- fnCheckName = function () end; -- 文件名限定函数
-- szResultPath = "e:\result.tab"; -- 文件搜索内容输出路径
-- szCmdResultPath = "e:\cmd_result.tab"; -- 自定义处理函数返回内容储存路径
--}
采用代码能够如下所示(貌似兼容网络路径的):
dofile("e:\search_log.lua");
tbTmpInfo = {};
function CheckInfo(szLine)
local szPlayerName, nPlayerId, nCount = string.match(szLine, "^.*szType = finalt[^t]+t%d+t([^t]+)t(%d+)t(%d+).*$");
nPlayerId = tonumber(nPlayerId);
nCount = tonumber(nCount);
if nCount > tbTmpInfo[nPlayerId] then
tbTmpInfo[nPlayerId] = nCount;
return "" .. nPlayerId .. "t" .. nCount;
end
return;
end
tbParam =
{
bIsMatch = false;
fnCmd2Line = CheckInfo;
fnCheckName = function () return true; end;
szResultPath = "e:\result.tab";
szCmdResultPath = "e:\cmd_result.tab";
}
DoSearchDir("d:\logs", "szType = final", tbParam);
for _, szInfo in pairs(tbTmpInfo) do
print(szInfo);
end
在这个场景下,唯一不满意的地方貌似是搜索速度有点慢,以后有空再调整吧,现在这个暂时够用了,至少比原来便于多了~~
您可能感兴趣的文章:
- Lua中轻松的错误处理实例
- Lua中的异常处理pcall、xpcall、debug采用实例
- Lua函数与字符串处理简明总结
- Lua极简入门指南(三): loadfile和错误处理
- Lua读取和写入文件处理例子
- 浅析Lua编程中的异常处理