Это спроектированное поведение FOR / F - он никогда не возвращает пустые строки. Работа заключается в том, чтобы использовать FIND или FINDSTR для префикса строки с номером строки. Если вы не можете гарантировать, что строки не начинаются с разделителя номера строки, тогда вы просто устанавливаете соответствующий разделитель и сохраняете токены 1 *, но используете только второй токен.
::preserve blank lines using FIND, assume no line starts with ]
::long lines are truncated
for /f "tokens=1* delims=]" %%A in ('type "file.txt" ^| find /n /v ""') do echo %%B
::preserve blank lines using FINDSTR, assume no line starts with :
::long lines > 8191 bytes are lost
for /f "tokens=1* delims=:" %%A in ('type "file.txt" ^| findstr /n "^"') do echo %%B
::FINDSTR variant that preserves long lines
type "file.txt" > "file.txt.tmp"
for /f "tokens=1* delims=:" %%A in ('findstr /n "^" "file.txt.tmp"') do echo %%B
del "file.txt.tmp"
Я предпочитаю FINDSTR - он более надежный , Например, FIND может обрезать длинные строки - FINDSTR не до тех пор, пока он читает непосредственно из файла. FINDSTR действительно отбрасывает длинные строки при чтении из stdin через канал или перенаправление.
Если файл может содержать строки, начинающиеся с разделителя, тогда вам нужно сохранить всю строку с префиксом номера строки, а затем использовать поиска и замены, чтобы удалить префикс строки. Вероятно, вы хотите отсрочить расширение при переносе %% A в переменную среды, иначе любой! будет поврежден. Но позже в цикле вам нужно отложить расширение, чтобы выполнить поиск и заменить.
::preserve blank lines using FIND, even if a line may start with ]
::long lines are truncated
for /f "delims=" %%A in ('type "file.txt" ^| find /n /v ""') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*]=!"
echo(!ln!
endlocal
)
::preserve blank lines using FINDSTR, even if a line may start with :
::long lines >8191 bytes are truncated
for /f "delims=*" %%A in ('type "file.txt" ^| findstr /n "^"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
::FINDSTR variant that preserves long lines
type "file.txt" >"file.txt.tmp"
for /f "delims=*" %%A in ('findstr /n "^" "file.txt.tmp"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
del "file.txt.tmp"
Если вам не нужно беспокоиться о преобразовании файла в ASCII, тогда более эффективно отбрасывать канал и пусть FIND или FINDSTR откроют файл, указанный в качестве аргумента, или путем перенаправления.
Существует еще одна работа, которая полностью обходит FOR / F во время процесса чтения. Это выглядит странно, но это более эффективно. Нет ограничений с использованием замедленного расширения, но, к сожалению, у него есть и другие ограничения.
1) строки должны быть завершены символом & lt; CR> & lt; LF> (это не будет проблемой, если вы используете ТИП преобразование файлов)
2) строки должны быть & lt; = 1021 байта (без учета & lt; CR> & lt; LF>)
3) любые конечные управляющие символы удаляются из каждого line.
4) он должен прочитать из файла - вы не можете использовать канал. Поэтому в вашем случае вам понадобится временный файл для преобразования ASCII.
setlocal enableDelayedExpansion
type "file.txt">"file.txt.tmp"
for /f %%N in ('find /c /v "" ^<"file.txt.tmp"') do set cnt=%%N
<"file.txt.tmp" (
for /l %%N in (1 1 %cnt%) do(
set "ln="
set /p "ln="
echo(!ln!
)
)
del "file.txt.tmp"