批处理脚本错误级别没有被重置。
批处理脚本错误级别没有被重置。
我正在编写一个小的BAT文件,它会搜索\"FAIL\"关键字后跟\"PASS\",如果找不到则将其视为错误:\n
echo set "topLevel=%cd%" 如果[%1]==[] 退出/B 1 如果[%2]==[] 退出/B 1 如果[%3]==[] 退出/B 1 如果[%4]==[] 退出/B 1 findstr /? >NUL 2>&1 || 退出/B 1 set "arg1=%1" set "arg2=%2" set "arg3=%3" set "arg4=%4" set /a errno=0 如果不存在%arg3% 退出/B 1 如果不存在%arg2%\%arg1% 退出/B 1 set "logfile=%arg1:.=_%" 复制/y/v %arg2%\%arg1% %arg3%\%arg4%.%logfile%.res || 退出/B 1 findstr /I /C:"FAIL" /I /C:"UNKNOWN" %arg3%\%arg4%.%logfile%.res 如果%errorlevel% EQU 0 ( set /a errno=2 ) ELSE ( REM 确保脚本没有崩溃,因此既不会列出PASS也不会列出FAIL findstr /I /C:"PASS" %arg3%\%arg4%.%logfile%.res 如果%errorlevel% NEQ 0 ( set /a errno=2 ) ) cd %topLevel% 退出/B %errno%
\n当我用示例数据运行时,我得到如下输出:\n
.............................................. C:\agent\_work\30\s1>copy /y/v C:\output\test.log C:\agent\_work\30\s1\tttt.test_log.res || 退出/B 1 1 file(s) copied. C:\agent\_work\30\s1>findstr /I /C:"FAIL" /I /C:"UNKNOWN" C:\agent\_work\30\s1\tttt.SystemWalk_log.res C:\agent\_work\30\s1>如果 1 EQU 0 (set /a errno=2 ) ELSE ( REM 确保脚本没有崩溃,因此既不会列出PASS也不会列出FAIL findstr /I /C:"PASS" C:\agent\_work\30\s1\tttt.test_log.res 如果 1 NEQ 0 (set /a errno=2 ) ) PASSED PASSED PASSED PASSED PASSED C:\agent\_work\30\s1>cd C:\agent\_work\30\s1 C:\agent\_work\30\s1>退出/B 2 C:\agent\_work\30\s1>echo %ERRORLEVEL% 2
\n实际上,因为找到了\"PASS\"字符串而没有找到\"FAIL\"字符串,所以错误级别应该是0 - 我该如何解决这个问题?
问题的原因是在批处理脚本中,错误级别(errorlevel)没有被重置。解决这个问题的方法是使用延迟环境变量扩展(delayedexpansion)或调用子程序进行进一步处理。
在批处理脚本中,当变量在一个括号内的一系列指令(也称为“代码块”)中发生变化时,需要使用延迟环境变量扩展来显示或使用运行时的变量值。在代码块语句(括号内的一系列语句)中,整个代码块首先被解析,然后执行。代码块中的任何%变量%都将被替换为在解析代码块时该变量的值 - 在执行代码块之前 - 对于FOR ... DO(代码块)也是如此。因此,IF(something)else(somethingelse)将使用在遇到IF时的%变量%的值执行。
克服这个问题的两种常见方法是:1)使用setlocal enabledelayedexpansion,并在使用改变后的变量值时使用!var!替代%var%;2)调用一个子程序来执行进一步的处理,使用改变后的值。
IF ERRORLEVEL n如果errorlevel是n或大于n,则为TRUE。因此,IF ERRORLEVEL 0始终为真。IF NOT ERRORLEVEL 1是对errorlevel=0的测试。IF %ERRORLEVEL%==0也是如此,只是前者可以在代码块中使用,而后者不行。