我正在尝试编写一个批处理文件,该文件扫描多个文件并查找字符串“WARNING
”。
到目前为止,我有:
FORFILES -m*.f08 -C"CMD /C FINDSTR /N "WARNING" ECHO @FILE >> ListOfWARNINGS
问题一:它不会在新行中打印每个找到的字符串。
问题二:如何更改代码并添加IF
语句,以便它还会在找到WARNING
的行之后打印该行。
答案 0 :(得分:2)
我认为,为了获得下一行,你实际上必须循环文件&据我所知,内容既不是forfiles也不是支持;
@echo off
setlocal enabledelayedexpansion
for %%f in (*.txt) do (
echo Search %%f
for /f "usebackq eol= delims=] tokens=1*" %%l in (`find /n /v "" "%%f"`) do (
set line=%%m
if !printnext!==1 (
echo.%%m >> ListOfWARNINGS
set printnext=0
) else (
if not [!line!]==[] if not !line!==!line:WARNING=X! (
echo %%m >> ListOfWARNINGS
set printnext=1
) else (
set printnext=0
)
)
)
)
此处if not !line!==!line:WARNING=X!
通过询问WARNING被替换为X后行是否等于自身来检测匹配。
C:\null>type a.txt
line 1
M O D E L S U M M A R Y
WARNING XXXXXXX
Line after warning
NUMBER OF CBAR ELEMENTS = 18655
lorem ipsum lorem ipsum lorem ipsum
WARNING ZZZZZZZ
C:\null>x.bat
Search a.txt
C:\null>type ListOfWARNINGS
WARNING XXXXXXX
Line after warning
WARNING ZZZZZZZ
C:\null>
答案 1 :(得分:1)
试试这个,
@ECHO OFF
:TOP
IF (%1)==() GOTO END
ECHO Value is "%1" and still running...
SHIFT
GOTO TOP
:END
请参阅此link
答案 2 :(得分:1)
Alex K解决方案效果很好,只要文件相对较小,它就能很好地运行。但是如果文件变大,性能就会成为一个主要问题。
我设置了一个包含4个文件的测试 - 3个小于1Kbyte的小文件,以及1个大~100byte文件。警告分散在文件中,包括大文件的开头和结尾附近。
Alex K解决方案 4.75分钟完成!问题是FOR IN()中的FINDSTR的整个结果集必须被缓存,而Windows对大数据集的效率非常低。
此外,该解决方案存在一个潜在的问题,即由于延迟扩展,它将损坏包含!
的任何文件名和/或数据行。这可以通过适当地切换延迟扩展来解决,也可以根据需要在ENDLOCAL边界保留变量值。
将结果写入临时文件然后使用FOR / F读取临时文件要快得多。我修改了代码以使用临时文件(未显示),时间缩短为 43秒。
但仍有更快的解决方案。与FINDSTR的速度相比,FOR循环在读取文件时非常慢。下面是一个解决方案,它使用FINDSTR为每个警告搜索每个文件一次,再加上2次。这似乎是很多额外的工作,但完成我的测试用例的时间减少到 1秒!
此解决方案还消除了文件名或文件内容中!
引起的任何问题。
该解决方案针对WARNING数量与文件中的行数相比相对较小的情况进行了优化。如果WARNING的数量开始接近文件中的行数,那么它实际上会比上述中间解决方案慢。
此解决方案还在每个警告前面加上文件名和行号。
@echo off
setlocal disableDelayedExpansion
set searchFiles="*.f08"
set outFile="ListOfWARNINGS"
set tempFile="%temp%\warnings%random%.txt"
set tempFile2="%temp%\warnings2_%random%.txt"
(
for /f "tokens=1,2 delims=:" %%A in ('findstr /m WARNING %searchFiles% nul') do (
findstr /n "^" "%%A" nul >%tempFile%
echo(>>%tempFile%
set "file=%%A"
set "next=0"
setlocal enableDelayedExpansion
findstr /n WARNING "!file!" >%tempFile2%
for /f "usebackq delims=:" %%N in (%tempFile2%) do (
if %%N==!next! (set "current=") else set current=/c:"!file!:%%N:"
set /a "next=%%N+1"
findstr /bi !current! /c:"!file!:!next!:" %tempFile%
)
endlocal
)
)>%outFile%
del %tempFile% 2>nul
del %tempFile2% 2>nul
最后一个FINDSTR中的/I
选项在逻辑上不应该是必需的。它可以防止FINDSTR有时会出现多个不同长度的文字搜索字符串的问题。