稍微处理一下批处理文件,并想知道为什么在以下场景中输出文件所需的时间存在巨大差异:
场景 1:简单遍历日志文件,并且对于每一行,始终采用第 5 个标记,除非它包含过滤字符串。
(for /f "tokens=5" %%a in (test.log) do @echo(%%a) | findstr /v "filter_1 filter_2" > !filter!.txt
这非常有效,浏览 50M 文件会在 10 秒内返回一个较小的 10Mb 文件。
场景 2:执行完全相同的操作,但在标记的前面和末尾添加一些内容,以便我可以输出为 xml 文件而不是文本文件。为此,我必须按如下方式重建它
echo ^<rows^> > test.xml
>>test.xml (
for /f "tokens=5" %%a in (
'findstr /v "filter1 filter2" test.log'
) do echo ^<r a="%%a"/^>
)
echo ^</rows^> >> test.xml
对于小文件它可以按预期工作,但对于大文件则需要永远。无论如何,有没有办法通过场景 2 实现我想要的效果,但使用场景 1 语法,因为这似乎更有效。
FOR /F 始终在开始任何迭代之前缓冲 IN() 子句的内容。对于读取文件以及处理命令的输出都是如此。然而,我相信命令输出的缓冲方式存在一些根本性的差异,这使得它在大输出时特别慢。Edit:MC ND 有一个很好的解释为什么大输出的缓冲这么慢 https://stackoverflow.com/a/23374733/1012053.
大多数人惊讶地发现,有时最快的批处理解决方案是将命令输出写入临时文件,然后使用 FOR /F 读取临时文件。只要您的磁盘驱动器速度很快,这就会很快。
我相信以下内容将大大加快速度:
findstr /v "filter1 filter2" test.log >test.log.mod
>test.xml (
echo ^<rows^>
for /f "tokens=5" %%A in (test.log.mod) do echo ^<r a="%%A"/^>
echo ^</rows^>
)
del test.log.mod
另一种选择是将 XML 包装器添加到原始管道的左侧,然后适当地修改 FINDSTR 过滤器。但上述解决方案可能仍然更快,具体取决于过滤掉的行数。
(
echo ^<rows^>
for /f "tokens=5" %%A in (test.log) do echo ^<r a="%%A"/^>
echo ^</rows^>
) | findstr /v /c:"modifiedFilter_1" /c:"modifiedFilter_2" > test.xml
FINDSTR 还需要/R
如果过滤器是正则表达式,则选项。
但更快的解决方案是使用 Windows 的 sed 之类的工具,或者 JScript/Batch 混合实用程序、我的 REPL.BAT 或 Aacini 的 FINDREPL.BAT。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)