酷徒LOGO

在一行中,如何取消命令的%errorlevel%?


问题:

我在 true ( 作为 Git Bash的一部分) 上有和 false 命令用于测试目的。

下面是基本内容:


C:>true



C:>echo %errorlevel%


0



C:>false



C:>echo %errorlevel%


1



上面的命令和它们的退出代码应该是( true 上的0false 上的1 )。

现在,我将通过以下命令对命令进行否定:


C:>true && false



C:>echo %errorlevel%


1



C:>false || true



C:>echo %errorlevel%


0



这也可以按预期。

现在,我如何同时组合两个条件,以否定命令?

假设我不知道命令的退出代码,我想做如下的事情:


SOMECMD && false || true



这是我的尝试:


C:>true && false || true



C:>echo %errorlevel%


0



C:>false || true && false



C:>echo %errorlevel%


1



上述结果不像预期的那样。 因此 true 后的仍然是 truefalsefalse

那么最简单的方法是不知道它的退出代码?

理想情况下在同一行上。 Linux中与 等价的东西( 比如。! truefalse )。!


回答 1:

我做了一些实验,这是我迄今为止发现的最好方法

  • 创建 not.bat 脚本并放入你的路径文件夹中
  • 
    @echo off
    
    
    if %ERRORLEVEL% EQU 0 (exit/b 1) else (exit/b 0)
    
    
    
    
  • 运行这里测试脚本以确认 not.bat 脚本是否正常工作
  • 
    @echo off
    
    
    :: check to see if true/false commands exist or fallback to cmd.exe
    
    
    :: note 9009 means MSG_DIR_BAD_COMMAND_OR_FILE according to https://stackoverflow.com/questions/23091906/official-ms-reference-for-cmd-exe-errorlevel-9009
    
    
    false 2>nul
    
    
    if %ERRORLEVEL% EQU 9009 (set CMDFALSE=cmd/c"exit 1") else (set CMDFALSE=false)
    
    
    true 2>nul
    
    
    if %ERRORLEVEL% EQU 9009 (set CMDTRUE=cmd/c"exit 0") else (set CMDTRUE=true)
    
    
    
    :: informational
    
    
    echo using '%CMDFALSE%' for false
    
    
    echo using '%CMDTRUE%' for true
    
    
    
    :: run the test
    
    
    %CMDFALSE%
    
    
    echo %ERRORLEVEL% - should be 1
    
    
    %CMDFALSE% & not
    
    
    echo %ERRORLEVEL% - should be 0
    
    
    
    %CMDTRUE%
    
    
    echo %ERRORLEVEL% - should be 0
    
    
    %CMDTRUE% & not
    
    
    echo %ERRORLEVEL% - should be 1
    
    
    
    

    当你运行测试脚本时,你应该看到这个输出

    
    using 'false' for false
    
    
    using 'true' for true
    
    
    1 - should be 1
    
    
    0 - should be 0
    
    
    0 - should be 0
    
    
    1 - should be 1
    
    
    
    

    现在你可以使用这里语法来反转 ERRORLEVEL。

    
    mycommand & not
    
    
    echo %ERRORLEVEL%
    
    
    
    

    或者,如果在批处理文件中使用它,请在前面添加 call

    
    mycommand & call not
    
    
    echo %ERRORLEVEL%
    
    
    
    

回答 2:

&&|| 与/否则不一样。

如果有/否则,保证只有一个分支会触发。

但是||总是会响应上次执行的命令的返回代码。 所以给出这样一条声明 cmd1 && cmd2 || cmd3 如果cmd1失败,cmd3将激发,或者如果cmd2失败。

给出以上情况,很明显,使用 &&|| 不可以能否定返回代码( 零到零,零到零)。

显然,如果你扔进 GOTO,或者打电话,或者。 但我怀疑这是不是你想要的。

我假设你想要一个内嵌的,自包含的构造,它将执行否定。

看起来你使用 %ERRORLEVEL%, 很舒适,但请记住 %ERRORLEVEL% 与命令的返回代码不一样。 例如许多内部命令成功,但它们不会将ERRORLEVEL设置为 0,而是将值保持不变。 &&|| 运算符响应 true 返回代码,而不查看 ERRORLEVEL。

我对ERRORLEVEL的否定是使用 SET/A 测试for零。 但是如果你要检查设置值的同一行上的ERRORLEVEL,则必须使用延迟扩展。


(2>null set/a 1/!ERRORLEVEL! &&call ||call)



2>null 除以 0时,隐藏错误消息。 当分区成功时,&&call<space> ( 有一个尾随的空间) 将ERROLEVEL设置为 0,而 ||call ( 没有尾随的空间) 将ERRORLEVEL设置为 1,除以 0. 括号使构造可以安全地使用内联。

你可以将代码保存在变量中,并像简单的宏一样使用它。 下面是一个完整的示例,演示了 %not% 宏的完全内联用法。


@echo off


setlocal enableDelayedExpansion



:: Note the delayed expansion requires the quoted! to be escaped as ^! while defining the macro


set"not=(2>nul set/a 1/^!errorlevel^!&&call ||call)"



for/l %%N in (-2 1 2) do (


 call :setErrorLevel %%N & %not% && echo SUCCESS!errorlevel! || echo FAILURE!errorlevel!


 echo(


)


exit/b



:setErrorLevel


echo Testing %1


exit/b %1



%not% 之前使用单个 & 是很重要的,这样它总是执行。

显然,你不必执行内联操作:


@echo off


setlocal enableDelayedExpansion



:: Note the delayed expansion requires the quoted! to be escaped as ^! while defining the macro


set"not=(2>nul set/a 1/^!errorlevel^!&&call ||call)"



for/l %%N in (-2 1 2) do (


 call :setErrorLevel %%N


 %not% 


 if errorlevel 1 (


 echo FAILURE!errorlevel! 


 ) else (


 echo SUCCESS!errorlevel!


 )


 echo(


)


exit/b



:setErrorLevel


echo Testing %1


exit/b %1



注意 echo( 只是打印一个比 echo. 更安全的空白行的方法。






Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备17041772号-2  |  如果智培  |  酷兔英语  |  帮酷