@ECHO off
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE.exe "build.properties" ^| FIND.exe /V ""`) DO (
ECHO --%%A--
)
pause
@ECHO off
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE.exe "build.properties" ^| FIND.exe /V ""`) DO (
ECHO --%%A--
)
pause
这是FOR /F的设计行为 - 它永远不会返回空行。解决方法是使用 FIND 或 FINDSTR 在行前加上行号。如果您可以保证没有行以行号分隔符开头,那么只需设置适当的分隔符并保留 tokens 1 *,但仅使用第二个 token。
::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就不会这样做。但是,通过管道或重定向从stdin读取时,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读取过程。它看起来很奇怪,但效率更高。使用延迟扩展没有限制,但不幸的是它有其他限制。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
编辑: 针对新评论的补充作为答案
在:DefinePipe子程序中的代码创建了一个名为pipe.com的88字节程序,基本上执行与此伪批处理代码等效的过程:
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版本中无法使用。
安东尼奥
%pipe%
包含可执行程序的编译代码),但如果您不介意,能否解释一下:set /PC char=
中的C是什么意思,以及这行代码如何只获取一个字符;%NewLine%
的内容在哪里定义;echo
命令为什么不将字符/空格和尾随换行符连接到%line%
上;最后,在每个第二次迭代中,所有单个字符都加入到哪个变量中?此外,是否无法创建64位版本? - user66001输出包括空行的文本行
这里是我为自己开发的一个方法。
将代码保存为批处理文件,比如SHOWALL.BAT,并将源文件作为命令行参数传递。
输出可以重定向或管道传输。
@echo off
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" ^< "%~1"') do echo.%%ba
exit /b
示例:
showall source.txt
showall source.txt >destination.txt
showall source.txt | FIND "string"
一个奇怪的地方是包含 '^<'(重定向),而不是仅执行以下操作:
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" "%~1"') do echo.%%ba
如果省略重定向,则会输出一个前导空行。
]
字符,如果存在像 \..\..\Windows\system32\calc.exe
这样的行,则 echo.
将失败。 - jeb]
字符。只有第一个或遇到*
为止。 - James K::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
)
ECHO !ln!
将打印ECHO is off
!这就是为什么我使用了ECHO(!ln!
的原因。 - dbenhamfor /f
(至少在Windows XP
上)默认似乎不会跳过行。(社区 - 请通过测试以下批处理命令来更新此答案以适用于您的Windows
版本和服务包)。
Windows XP
中,似乎ping
命令会导致for /f
生成<CR>
而不是空行(如果有人知道为什么,请更新此答案或评论)。
作为一种解决方法,似乎第二个默认的分隔符标记(例如<space>
/ %%b
)
返回blank
,这对于通过“父级”方式消除空行的情况非常有效
在for /f
开头的第二个标记上设置“if”条件,就像这样:
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上看到的,它们是我能够轻松访问的三个版本和服务包:
CR
,您可以调用类似于 :trimmer <LF> set "trim=%1"
的函数,这个方法有效,因为在百分号扩展阶段后所有的 CR
都会被删除。但是如果有更多问题,您应该开一个新的问题。 - jebfor /f
并没有完全忽略空行,我猜它是在Win XP上删除了lf
,但没有删除cr
。我只是将其放在引号中以查看输出内容。 - user66001
ECHO.
更可靠。有些模糊的情况下,ECHO.
可能会失败,而ECHO(
从不失败。任何一种语法的重点都是允许输出空行。 - dbenham