Windows Batch:findstr未在for循环中设置ERRORLEVEL

问题描述 投票:1回答:4

任何人都可以向我解释为什么以下代码片段打印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来说有点新手,所以这对我来说有点神秘,因为这两个陈述似乎是无关的。任何帮助都将不胜感激,谢谢!

windows batch-file cmd windows-10 command-prompt
4个回答
5
投票

问题是在code block(带括号系列的陈述)中,任何%var%都将被parse time变量的实际值所取代。

欣你的第一个例子,%errorlevel% 0并如此回应。在第二个例子中,当遇到1时它是for,因此它被1取代。

如果要显示可在循环内更改的环境变量的值,则需要执行以下三项操作之一:

  1. 调用qazxsw poi和echo qazxsw poi而不是qazxsw poi - 注意你可以激活的嵌套setlocal enabledelayedexpansion指令的数量是有限的。
  2. 调用子程序
  3. 使用语法漏洞利用。

关于!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

0
投票

更新:

如果你在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

0
投票
echo %errorlevel%

这应该工作。

cmd中的for循环在技术上是一行,因此变量只展开一次。使用感叹号而不是百分比和“ENABLEDELAYEDEXPANSION”应该修复它。


0
投票
C:\>echo blahbin | findstr bin
blahbin
C:\>echo %errorlevel%
0            ; success / found it..
© www.soinside.com 2019 - 2024. All rights reserved.