任何人都可以向我解释为什么以下代码片段打印0
:
@echo off
setlocal
for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
echo %ERRORLEVEL%
)
在for-loop之外添加另一个等效语句使其打印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来说有点新手,所以这对我来说有点神秘,因为这两个陈述似乎是无关的。任何帮助都将不胜感激,谢谢!
问题是在code block
(带括号系列的陈述)中,任何%var%
都将被parse time
变量的实际值所取代。
欣你的第一个例子,%errorlevel%
0
并如此回应。在第二个例子中,当遇到1
时它是for
,因此它被1
取代。
如果要显示可在循环内更改的环境变量的值,则需要执行以下三项操作之一:
setlocal enabledelayedexpansion
指令的数量是有限的。关于!var!
的文章有很多很多。
粗略的,你可以简单地使用(注意 - 案例在批处理中基本上是无关紧要的,除了循环控制变量的情况(在这个例子中是%var%
- setlocal
)
delayedexpansion
另一种方法是动态调用metavariable
%%i
这样做的缺点是,@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为n或大于n”
或 - 调用子程序:
run-time
请注意errorlevel
(这里冒号很重要 - 这意味着“转到物理文件末尾”
或者,使用子例程的特殊版本 - 语法漏洞利用
if errorlevel n
更新:
如果你在for语句的结束@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%%
)
我有点猜测,因为确切的“确定”原因,但echo %ERRORLEVEL%
肯定会导致它。我假设for循环中ERRORLEVEL的值是)
语句的结果。这似乎是一种奇怪的行为,但我在批处理文件中看到的情况更糟。
如果你在开头删除for /f %%i in ('cmd /c echo blah') do (
echo %%i | findstr bin > NUL
)
echo %ERRORLEVEL%
它就像人们通常期望的那样工作..
原版的:
setlocal
在运行时设置cmd /c ...
。所以,setlocal
将始终输出0。
例如,以下findstr语句成功,因此它输出带匹配的行(传递给它的唯一行):
findstr
虽然此语句不成功(findstr不输出任何内容)并且errorlevel设置为1:
errorlevel
echo %errorlevel%
这应该工作。
cmd中的for循环在技术上是一行,因此变量只展开一次。使用感叹号而不是百分比和“ENABLEDELAYEDEXPANSION”应该修复它。
C:\>echo blahbin | findstr bin
blahbin
C:\>echo %errorlevel%
0 ; success / found it..