Это спроектированное поведение 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 пропускает длинные строки при чтении со стандартного ввода через канал или перенаправление.
Если файл может содержать строки, начинающиеся с разделителя, вам необходимо сохранить всю строку с префиксом номера строки, а затем использовать поиск и замену, чтобы удалить префикс строки. Вы, вероятно, хотите отключить отложенное расширение при переносе %% 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) строки должны заканчиваться (это не будет проблемой, если вы выполните преобразование файла ТИПА)
2) строки должны быть <= 1021 байт (без учета <CR>)
3) любые управляющие символы убираются из каждой строки.
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"