过滤批量输出

时间:2014-05-28 09:15:58

标签: batch-file

有没有办法使用正则表达式或类似方法过滤批处理文件的输出?

简而言之,这是我的方案:我需要清理日志文件以进行进一步分析,但由于它们的大小,我想先缩小它们的尺寸。原始文件是一个以空格分隔的文件,我知道每行第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
...

有任何建议吗?

4 个答案:

答案 0 :(得分:2)

选项1 - 纯原生批次

@echo off
setlocal disableDelayedExpansion
>cleaned.txt (
  for /f "tokens=5" %%A in (
    'findstr /rvc:"^ *[^ ]*  *[^ ]*  *[^ ]*  *[^ ]*  *test.html" test.log'
  ) do echo %%A
)

以上策略可以提高性能:

  • 使用FINDSTR预过滤掉所有test.html行
  • 使用FOR / F直接解析第5个令牌来消除CALL
  • 使用外部括号块
  • 仅重定向一次

<强> 更新

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