任何人都可以向我解释为什么以下代码片段会打印出 0
:
@echo off
setlocal
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
echo %ERRORLEVEL%
)
在 for 循环之外添加另一个等效语句时,它会打印 1 1
:
@echo off
setlocal
echo blah | findstr bin > NUL
echo %ERRORLEVEL%
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
echo %ERRORLEVEL%
)
我是 Batch 的新手,所以这对我来说有点神秘,因为这两个语句似乎无关。如有任何帮助,我们将不胜感激,谢谢!
最佳答案
问题在于,在代码块
(括号内的一系列语句)中,任何%var%
都将被parse 中变量的实际值替换时间
。
在您的第一个示例中,%errorlevel%
0
并这样回显。在第二个例子中,当遇到 for
时,它是 1
,因此它被替换为 1
。
如果你想显示一个可能在循环中改变的环境变量的值,那么你需要做以下三件事之一:
调用
setlocal enabledelayedexpansion
并回显!var!
而不是%var%
- 注意嵌套的数量您可以激活的 setlocal
指令是有限的。调用子程序
使用语法漏洞。
SO上有很多很多关于delayedexpansion
的文章。
粗略地说,您可以简单地使用(注意 - 大小写在批处理中基本上是不相关的,除了循环控制变量的情况(元变量
- %%i
in这个实例)
@echo off
setlocal ENABLEDELAYEDEXPANSION
echo blah | findstr bin > NUL
echo %ERRORLEVEL% or !errorlevel!
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
echo %ERRORLEVEL% or !errorlevel!
)
另一种方法是动态调用setlocal
@echo off
setlocal
echo blah | findstr bin > NUL
echo %ERRORLEVEL% or !errorlevel!
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
setlocal ENABLEDELAYEDEXPANSION
echo %ERRORLEVEL% or !errorlevel!
endlocal
)
这样做的缺点是 endlocal
会取消自上次 setlocal
以来对环境所做的任何更改。另请注意,如果 delayedexpansion
未生效,则 !
不再是特殊字符。
或者,您可以按传统方式使用 errorlevel
:
@echo off
setlocal
echo blah | findstr bin > NUL
echo %ERRORLEVEL% or !errorlevel!
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
if errorlevel 1 (echo errorlevel is 1 or greater
) else (echo errorlevel is 0
)
)
请注意,这会查看 errorlevel
的 run-time
值,if errorlevel n
表示“if errorlevel is n or大于 n"
或者 - 调用一个子程序:
@echo off
setlocal
echo blah | findstr bin > NUL
echo %ERRORLEVEL% or !errorlevel!
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
call :show
)
goto :eof
:show
echo %ERRORLEVEL%
goto :eof
注意这里 goto :eof
(这里的冒号很重要 - 这意味着“转到物理文件末尾”
或者,使用子程序的特殊版本——语法漏洞利用
@echo off
setlocal
echo blah | findstr bin > NUL
echo %ERRORLEVEL% or !errorlevel!
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
call echo %%errorlevel%%
)
关于Windows 批处理 : findstr not setting ERRORLEVEL within a for loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36237636/