Пакет DOS для цикла с FIND.exe удаляет пустые строки?

этот пакетный скрипт DOS удаляет пустые строки и не показывает пустые строки в файле, хотя я использую тип.exe команда для преобразования файла, чтобы убедиться, что файл ASCII так, что команда FIND совместим с файлом. Может ли кто-нибудь сказать мне, как заставить этот скрипт включать пустые строки?

@ECHO off
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE.exe "build.properties" ^| FIND.exe /V ""`) DO (
  ECHO --%%A--
)
pause

5 ответов


это разработанное поведение FOR / F - оно никогда не возвращает пустые строки. Работа заключается в использовании FIND или FINDSTR для префикса строки с номером строки. Если вы можете гарантировать, что строки не начинаются с разделителя номера строки, вы просто установите соответствующий разделитель и сохраните токены 1*, но используйте только 2-й токен.

::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 через канал или перенаправление.

Если файл может содержать строки, начинающиеся с разделителя, то необходимо сохранить всю строку с префиксом номера строки, а затем использовать search and replace для удаления префикса строки. Вероятно, вы хотите отключить отложенное расширение при передаче %%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) строки должны быть длиной )

3) любые конечные управляющие символы удаляются из каждой строки.

4) он должен читать из файла - вы не можете использовать трубы. Поэтому в вашем случае вам нужно будет использовать файл temp для преобразования в 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"

Я написал очень простую программу, которая может служить в качестве замены FIND и FINDSTR команды, когда они используются для этой цели. Моя программа называется PIPE.COM и он просто вставляет пустое пространство в пустые строки, поэтому все строки могут быть непосредственно обработаны FOR команда без дальнейших корректировок (пока вставленное пространство не заботится). Вот это:

@ECHO off
if not exist pipe.com call :DefinePipe
FOR /F "USEBACKQ delims=" %%A IN (`pipe ^< "build.properties"`) DO (
  ECHO(--%%A--
)
pause
goto :EOF

:DefinePipe
setlocal DisableDelayedExpansion
set pipe=´)€ì!Í!ŠÐŠà€Ä!€ü.t2€ü+u!:æu8²A€ê!´#€ì!Í!².€ê!´#€ì!Í!²+€ê!´#€ì!Í!Šò€Æ!´,€ì!Í!"Àu°´LÍ!ëÒ
setlocal EnableDelayedExpansion
echo !pipe!>pipe.com
exit /B

редактировать: добавление как ответ на новый комментарий

код at: DefinePipe подпрограмма создать программу 88 байт называется pipe.com, что в основном делает процесс, эквивалентный этому псевдо-пакетному коду:

set "space= "
set line=
:nextChar
   rem Read just ONE character
   set /PC char=
   if %char% neq %NewLine% (
      rem Join new char to current line
      set line=%line%%char%
   ) else (
      rem End of line detected
      if defined line (
         rem Show current line
         echo %line%
         set line=
      ) else (
         rem Empty line: change it by one space
         echo %space%
      )
   )
goto nextChar

таким образом, пустые строки во входном файле изменяются строками с одним пробелом, поэтому команда FOR /F больше не опускает их. Это работает "до тех пор, пока вставленное пространство не заботится", как я сказал в своем ответе.

обратите внимание, что pipe.com программа не работает в 64-битных версиях Windows.

Антонио


выходные строки, включая пустые строки

вот метод, который я разработал для собственного использования.

сохраните код в виде пакетного файла, скажем,SHOWALL.Летучая мышь!--11--> и передать исходный файл в качестве параметра командной строки.

выход можно перенаправить или пипед.

@echo off

for /f "tokens=1,* delims=]" %%a in ('find /n /v "" ^< "%~1"') do echo.%%ba

exit /b

примеры:

showall источник.txt

showall источник.txt >назначения.txt

showall источник.txt | найти "строку"

странностью является включение '^' (перенаправление), а не просто делать следующее:

for /f "tokens=1,* delims=]" %%a in ('find /n /v "" "%~1"') do echo.%%ba

опуская перенаправление, выводится ведущая пустая строка.


благодаря dbenham это работает, хотя это немного отличается от его предложения:

::preserve blank lines using FIND, no limitations
for /f "USEBACKQ delims=" %%A in (`type "file.properties" ^| find /V /N ""`) do (
  set "ln=%%A"
  setlocal enableDelayedExpansion
  set "ln=!ln:*]=!"
  echo(!ln!
  endlocal
)

как говорится в этой ответ на вышеуказанный вопрос, не кажется, что строки пропускаются по умолчанию с помощью for /f in (по крайней мере) Windows XP (сообщество-обновите этот ответ, Протестировав приведенные ниже пакетные команды в вашей версии и пакете обновления Windows).


    EDIT: Per Джеб ' s комментарий ниже кажется, что ping команда, по крайней мере Windows XP, is
   вызывая for /f в производить <CR>вместо пустых строк (Если кто-то знает конкретно почему, будет
   оцените, если они могут обновить этот ответ или комментарий).

в качестве обходного пути кажется, что второй маркер с разделителями по умолчанию (<space> / %%b в пример)
   возвращается как blank, который работал для моей ситуации устранения пустых строк с помощью "родителя"
   if условно на втором токене в начале for /f, как это:

   for /f "tokens=1,2*" %%a in ('ping -n 1 google.com') do (
      if not "x%%b"=="x" (
         {do things with non-blank lines}
      )
   )



Используя приведенный ниже код:

@echo off
systeminfo | findstr /b /c:"OS Name" /c:"OS Version" 
echo.&echo.
ping -n 1 google.com
echo.&echo.
for /f %%a in ('ping -n 1 google.com') do ( echo "%%a" )
echo.&echo.&echo --------------&echo.&echo.
find /?
echo.&echo.
for /f %%a in ('find /?') do ( echo "%%a" )
echo.&echo.
pause

.... ниже приведено то, что я вижу в Windows XP, Windows 7 и Windows 2008, являясь единственными тремя версиями и пакетами обновлений Windows, к которым у меня есть готовый доступ:

Windows XP Pro SP3

Windows 7 Enterprise SP1

Windows Server 2008 R2 Enterprise SP1