Решение Alex K прекрасно работает и работает хорошо, если файлы относительно небольшие.Но если файлы становятся большими, производительность может стать серьезной проблемой.
Я настроил тест с 4 файлами - 3 маленьких файла размером менее 1 КБ, плюс 1 большой файл ~ 1 МБ.В файлах разбросаны ПРЕДУПРЕЖДЕНИЯ, в том числе около начала и конца большого файла.
Решение Alex K заняло 4,75 минут для завершения!Проблема в том, что весь набор результатов FINDSTR в FOR IN () должен быть кэширован, и Windows делает это очень неэффективно с большими наборами данных.
Также у решения есть потенциальная проблема в том, что оно повредит любые имена файлов и / или строки данных, которые содержат !
из-за задержки расширения.Это можно исправить, включив и отключив отложенное расширение, также по мере необходимости сохраняя значения переменных через границу ENDLOCAL.
Гораздо быстрее записать результаты во временный файл и затем использоватьFOR / F для чтения временного файла.Я изменил код, чтобы использовать временный файл (не показан), и время было сокращено до 43 секунд.
Но есть еще более быстрое решение.Цикл FOR чрезвычайно медленный при чтении файла по сравнению со скоростью FINDSTR.Ниже приведено решение, которое использует FINDSTR для поиска каждого файла один раз для каждого предупреждения, плюс еще 2 раза.Это выглядит как дополнительная работа, но время для завершения моего теста сокращено до 1 секунда !
Это решение также устраняет любые проблемы, связанные с !
в именах файлов.или содержимое файла.
Решение оптимизировано для случаев, когда количество ПРЕДУПРЕЖДЕНИЙ относительно мало по сравнению с количеством строк в файле.Если число ПРЕДУПРЕЖДЕНИЙ начинает приближаться к количеству строк в файле, то оно фактически станет медленнее, чем среднее решение, описанное выше.
Это решение также добавляет к каждому предупреждению префикс с именем файла и строкой.number.
@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
Опция /I
в последнем FINDSTR логически не обязательна.Он предназначен для защиты от ошибки, когда у FINDSTR иногда возникают проблемы с несколькими строками поиска букв различной длины.