有没有办法使用正则表达式或类似方法过滤批处理文件的输出?
简而言之,这是我的方案:我需要清理日志文件以进行进一步分析,但由于它们的大小,我想先缩小它们的尺寸。原始文件是一个以空格分隔的文件,我知道每行第5项都是我需要的。
到目前为止这么好,以下文件给了我我需要的东西:
@echo off & setLocal enableDELAYedexpansion
@title = logger
for /f "tokens=*" %%a in (test.log) do call :getURI %%a
pause
goto :eof
:getURI
echo %5 >> cleaned.txt
goto :eof
:eof
这给了我想要的输出如下
some_url.html
test.html
some_other_url.html
test.html
test.html
yet_another_url.html
...
现在,生成这个文件还需要很多时间,所以我想知道是否有更有效的方法来做到这一点,以及是否也可以过滤输出。我仍然在输出(虚构的例子)中有相当一些[test.html],我更喜欢将它们排除在前面,所以我的结果将成为
some_url.html
some_other_url.html
yet_another_url.html
...
有任何建议吗?
答案 0 :(得分:2)
选项1 - 纯原生批次
@echo off
setlocal disableDelayedExpansion
>cleaned.txt (
for /f "tokens=5" %%A in (
'findstr /rvc:"^ *[^ ]* *[^ ]* *[^ ]* *[^ ]* *test.html" test.log'
) do echo %%A
)
以上策略可以提高性能:
<强> 更新 强>
如this follow up question中所述,在处理非常大的文件时,此解决方案变得非常慢。使用临时文件可以恢复良好的性能。
@echo off
setlocal disableDelayedExpansion
findstr /rvc:"^ *[^ ]* *[^ ]* *[^ ]* *[^ ]* *test.html" test.log >test.log.mod
>cleaned.txt (for /f "tokens=5" %%A in (test.log.mod) do echo %%A)
del test.log.mod
选项2 - 我的REPL.BAT实用程序
我写了hybrid JScript/batch utility called REPL.BAT,可以非常有效地直接提供所需的结果。它执行正则表达式搜索并替换stdin并将结果写入stdout。它是纯脚本,可以在任何现代Windows机器上从XP开始本地运行。
type test.log | repl "^ *(\S+ +){4}(?!test.html |test.html$)(\S*).*" $2 a >cleaned.txt
答案 1 :(得分:1)
这应该比原始代码运行得更快,并且还会消除test.html
:
echo off & setLocal enableDELAYedexpansion
@title = logger
(for /f "tokens=5" %%a in (test.log) do (
if "%%a" neq "test.html" echo %%a
)) > cleaned.txt
pause
答案 2 :(得分:1)
@echo off
setlocal enableextensions disabledelayedexpansion
( for /f "tokens=5" %%a in (test.log) do @echo(%%a
) | findstr /v /b /c:"test.html" /c:"another_test.html" > cleaned.txt
endlocal
for命令将标记输入文件的行,拆分空格(默认行为)。我们只对将要回应的第五个(tokens=5
)感兴趣。 for
命令执行的输出通过管道传送到findstr
,该行将在行的开头(/v
)显示所有不包含(/b
)的行指示的字符串(/c:"..."
)
答案 3 :(得分:0)
您可以在grep中运行-v选项,它会反转所有匹配的行,为您提供与搜索不匹配的所有行。
grep -v "test.htm" > newfile.log
-v的{p> Explanation位于Gnu网站。
可以根据需要多次将命令堆叠在一起:
grep -v "firstunwanted" * | grep -v "secondunwanted" > newfile.log