日志文件状态变更记录过滤需求及批处理脚本问题
日志文件状态变更记录过滤需求及批处理脚本问题
我来帮你解决这个日志过滤的问题!先理清楚你的需求和现有脚本的问题,再给出修正后的解决方案。
需求说明
你有一个日志文件(比如2024-04-29_22-23log.txt),格式规则如下:
- 第一行是日志的标识头
- 从第二行开始,每一行以
OPEN或CLOSE开头,后面跟着时间戳
你期望的过滤规则是:
- 必须保留第一行
- 只保留那些和上一行状态(OPEN/CLOSE)不同的行
- 无论最后一行的状态是什么,必须保留它
原始日志示例
2024-04-29_22-23 CLOSE 22:23 CLOSE 22:24 OPEN 22:25 OPEN 22:26 OPEN 22:27 CLOSE 22:28 CLOSE 22:29 CLOSE 22:30
期望输出示例
2024-04-29_22-23 CLOSE 22:23 OPEN 22:25 CLOSE 22:28 CLOSE 22:30
现有脚本的问题
你提到的现有批处理脚本存在两个明显问题:
- 只能处理纯字母组成的文件名,遇到带日期、下划线这类特殊字符的文件名会解析出错
- 会漏掉最后一行,不符合你“必须保留最后一行”的需求
修正后的批处理脚本
下面是修复后的脚本,完美解决了上述两个问题:
@echo off setlocal enabledelayedexpansion set /p "inputFile=Enter file name : " set "outputFile=!inputFile!_filtered.txt" rem 初始化变量 set "previousState=" set "lastLine=" set "firstLineDone=0" rem 清空输出文件(如果已存在) type nul > "!outputFile!" rem 逐行读取输入文件 for /f "usebackq delims=" %%a in ("!inputFile!") do ( rem 处理第一行:直接写入输出文件 if !firstLineDone! equ 0 ( echo %%a>>"!outputFile!" set "firstLineDone=1" set "lastLine=%%a" continue ) rem 提取当前行的状态(OPEN/CLOSE) for /f "tokens=1" %%b in ("%%a") do set "currentState=%%b" rem 记录最后一行内容 set "lastLine=%%a" rem 如果当前状态和上一个状态不同,写入输出文件 if not "!currentState!"=="!previousState!" ( echo %%a>>"!outputFile!" set "previousState=!currentState!" ) ) rem 检查最后一行是否已在输出文件中,未存在则追加 findstr /x /c:"!lastLine!" "!outputFile!" >nul || echo !lastLine!>>"!outputFile!" echo Filtering completed! Output saved to "!outputFile!" endlocal
脚本关键点说明
- 用
usebackq参数支持带特殊字符(如横杠、下划线)的文件名,避免解析错误 - 新增
lastLine变量全程记录每行内容,循环结束后检查并确保最后一行被保留 - 用
firstLineDone标记确保第一行必被写入 - 通过
tokens=1提取每行的状态关键词,和上一行状态对比,仅保留状态变更的行
备注:内容来源于stack exchange,提问作者smbd91 smbd91
相关产品推荐
相关产品推荐

