如何正确地批量检查参数是否存在?
How to correctly check the presence of parameters in batch?
我现在尝试对一个简单的网络脚本进行批处理 3 个小时,但我一直在检查参数。
我实际用
IF not "%~1"=="" ( IF not "%~2"=="" (
Set NHS_Network1 = %1
Set NHS_Router1 = %2
))
执行时仍然出现语法错误。
这是我已经尝试过的:
IF DEFINED
:不适用于参数
IF [%1]NEQ[] ( IF [%2]NEQ[] ( ... ))
导致错误(出乎意料
所以...我现在很困惑。我从未批量做过 "complex" 事情,但我熟悉 bash、C、C++、Java、...
完整代码可能有一些错误,因为我卡在了开头。
REM #Configuration#
Set NHS_Network1 = 192.168.0.0/24
Set NHS_Router1 = 192.168.0.254
Set NHS_Network2 = 192.168.1.0/24
Set NHS_Router2 = 192.168.1.1
Set NHS_Gateway1 = 192.168.1.1
Set NHS_Gateway2 = 192.168.0.254
Echo Network Home Script V0.1
IF not "%~1"=="" ( IF not "%~2"=="" (
Echo Overwriting Configuration
REM #Reset#
Set NHS_Network1 = []
Set NHS_Router1 = []
Set NHS_Network2 = []
Set NHS_Router2 = []
Set NHS_Gateway1 = []
Set NHS_Gateway2 = []
REM #Variable setup#
Set NHS_Network1 = %1
Set NHS_Router1 = %2
))
IF not "%~3"=="" ( IF not "%~4"=="" (
Set NHS_Network2 = %3
Set NHS_Router2 = %4
))
IF not "%~5"==""(
Set NHS_Gateway1 = %5
)
IF not "%~6"=="" (
Set NHS_Gateway2 = %6
)
IF DEFINED %NHS_Network1% ( IF DEFINED %NHS_Router1% (
route delete %NHS_Network1%
route add %NHS_Network1% %NHS_Router1%
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
))
IF DEFINED %NHS_Network2% ( IF DEFINED %NHS_Router2% (
route delete %NHS_Network2%
route add %NHS_Network2% %NHS_Router2%
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
))
IF DEFINED %NHS_Gateway1% (
route delete 0.0.0.0/0
route add 0.0.0.0/0 %NHS_Gateway1% metric 10
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
)
IF DEFINED %NHS_Gateway2% (
route add 0.0.0.0/0 %NHS_Gateway2% metric 20
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
)
请阅读 Why is no string output with 'echo %var%' after using 'set var = text' on command line? 上的答案以了解为什么在批处理文件中将 1 个或多个 space 放在等号周围以将字符串分配给环境变量。
并阅读 this answer 解释批处理文件中 IF 条件的正确语法。在批处理文件中必须小心使用空格。在某些位置上需要 space,在其他位置上 space 通常是错误的。
并且必须注意在使用 (
... )
定义的块中引用环境变量的值,因为命令处理器使用 %variable%
替换对环境变量的所有引用在处理块中的行之前,通过它们在整个块中的值来语法。对于在块内定义或设置并在块内求值的环境变量,有必要启用延迟扩展并使用 !variable!
引用这些变量以使用延迟扩展。更好的是避免延迟环境变量扩展的需要。
goto 是 C/C++ 中很少使用的关键字。但在批处理文件中,它是一个非常重要的命令,它的使用使大多数批处理文件比使用 C/C++ 中使用的嵌套 IF 结构要容易得多,以避免使用 转到.
评估批处理文件的参数有一个通用规则:
如果没有定义第一个参数,则肯定没有更多的参数。
嗯,可以使用例如 "" "second parameter" ThirdParameter
调用批处理文件 运行 它带有 3 个参数,其中第一个是空字符串。但是对于您的脚本,可以将空字符串解释为根本未指定参数。
这是使用 goto 重新编码的批处理文件,避免了延迟扩展的需要。
@echo off
echo Network Home Script V0.1
setlocal
rem Default configuration
set "NHS_Network1=192.168.0.0/24"
set "NHS_Router1=192.168.0.254"
set "NHS_Network2=192.168.1.0/24"
set "NHS_Router2=192.168.1.1"
set "NHS_Gateway1=192.168.1.1"
set "NHS_Gateway2=192.168.0.254"
rem Run script with the defaults if executed without any
rem parameter or with just 1 parameter for first network.
if "%~1"=="" goto SetRoutes
if "%~2"=="" goto SetRoutes
rem IPv4 address with netmask and router address defined for network 1.
set "NHS_Network1=%~1"
set "NHS_Router1=%~2"
rem Delete all other by default defined environment variables.
set "NHS_Network2="
set "NHS_Router2="
set "NHS_Gateway1="
set "NHS_Gateway2="
if "%~3"=="" goto SetRoutes
if "%~4"=="" goto SetRoutes
rem IPv4 address with netmask and router address defined for network 2.
set "NHS_Network2=%~3"
set "NHS_Router2=%~4"
rem Set the gateway addresses if defined as fifth and sixth parameter.
if not "%~5"=="" set "NHS_Gateway1=%~5"
if not "%~6"=="" set "NHS_Gateway2=%~6"
:SetRoutes
rem The variables NHS_Network1 and NHS_Router1 are always defined.
%SystemRoot%\System32\route.exe delete %NHS_Network1%
%SystemRoot%\System32\route.exe add %NHS_Network1% %NHS_Router1%
if errorlevel 1 (
echo ERROR : Impossible to add route for network 1, please check route print.
) else (
echo Route for network 1 added.
)
rem NHS_Router2 is always defined if NHS_Network2 is defined.
if defined NHS_Network2 (
%SystemRoot%\System32\route.exe delete %NHS_Network2%
%SystemRoot%\System32\route.exe add %NHS_Network2% %NHS_Router2%
if errorlevel 1 (
echo ERROR : Impossible to add route for network 2, please check route print.
) else (
echo Route for network 2 added.
)
)
if defined NHS_Gateway1 (
%SystemRoot%\System32\route.exe delete 0.0.0.0/0
%SystemRoot%\System32\route.exe add 0.0.0.0/0 %NHS_Gateway1% metric 10
if errorlevel 1 (
echo ERROR : Impossible to add route for gateway 1, please check route print.
) else (
echo Route for gateway 1 added.
)
)
if defined NHS_Gateway2 (
%SystemRoot%\System32\route.exe add 0.0.0.0/0 %NHS_Gateway2% metric 20
if errorlevel 1 (
echo ERROR : Impossible to add route for gateway 2, please check route print.
) else (
echo Route for gateway 2 added.
)
)
endlocal
另请参阅 Microsoft 支持文章 Testing for a Specific Error Level in Batch Files。
if errorlevel 1
的用法 - 意味着如果先前命令或应用程序的退出代码大于或等于 1 - 优于在块中使用 %ERRORLEVEL%
作为命令处理器替换 %ERRORLEVEL%
在完全执行上面的行之前,已经根据此变量的当前值解析块。如果不使用特殊语法来检查错误级别,则有必要使用延迟扩展。
要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
endlocal /?
if /?
rem /?
route /?
set /?
setlocal /?
@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET args=%*
FOR %%a IN (NHS_Network1:192.168.0.0/24
NHS_Router1:192.168.0.254
NHS_Network2:192.168.1.0/24
NHS_Router2:192.168.1.1
NHS_Gateway1:192.168.1.1
NHS_Gateway2:192.168.0.254
) DO FOR /f "tokens=1,2delims=:" %%v IN ("%%a") DO (
FOR /f "tokens=1*" %%t IN ('echo !args!') DO (
IF "%%~t"=="" (SET "%%v=%%w") ELSE (SET "%%v=%%~t")
IF DEFINED args (SET "args=%%u") ELSE (SET "%%v=%%w")
)
)
SET nhs
GOTO :EOF
如果需要,可以添加其他数据 - 格式应该是显而易见的。
将 args
设置为提供给批处理的参数列表。
对于每个 varname:varvalue,将 %%v
分配给变量名并 %%w
默认值。
将变量设置为第一个剩余参数或默认值
如果还有剩余参数,请删除一个。否则,使用默认值。
与原版不完全相同,但可能有用。
我现在尝试对一个简单的网络脚本进行批处理 3 个小时,但我一直在检查参数。
我实际用
IF not "%~1"=="" ( IF not "%~2"=="" (
Set NHS_Network1 = %1
Set NHS_Router1 = %2
))
执行时仍然出现语法错误。
这是我已经尝试过的:
IF DEFINED
:不适用于参数IF [%1]NEQ[] ( IF [%2]NEQ[] ( ... ))
导致错误(出乎意料
所以...我现在很困惑。我从未批量做过 "complex" 事情,但我熟悉 bash、C、C++、Java、...
完整代码可能有一些错误,因为我卡在了开头。
REM #Configuration#
Set NHS_Network1 = 192.168.0.0/24
Set NHS_Router1 = 192.168.0.254
Set NHS_Network2 = 192.168.1.0/24
Set NHS_Router2 = 192.168.1.1
Set NHS_Gateway1 = 192.168.1.1
Set NHS_Gateway2 = 192.168.0.254
Echo Network Home Script V0.1
IF not "%~1"=="" ( IF not "%~2"=="" (
Echo Overwriting Configuration
REM #Reset#
Set NHS_Network1 = []
Set NHS_Router1 = []
Set NHS_Network2 = []
Set NHS_Router2 = []
Set NHS_Gateway1 = []
Set NHS_Gateway2 = []
REM #Variable setup#
Set NHS_Network1 = %1
Set NHS_Router1 = %2
))
IF not "%~3"=="" ( IF not "%~4"=="" (
Set NHS_Network2 = %3
Set NHS_Router2 = %4
))
IF not "%~5"==""(
Set NHS_Gateway1 = %5
)
IF not "%~6"=="" (
Set NHS_Gateway2 = %6
)
IF DEFINED %NHS_Network1% ( IF DEFINED %NHS_Router1% (
route delete %NHS_Network1%
route add %NHS_Network1% %NHS_Router1%
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
))
IF DEFINED %NHS_Network2% ( IF DEFINED %NHS_Router2% (
route delete %NHS_Network2%
route add %NHS_Network2% %NHS_Router2%
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
))
IF DEFINED %NHS_Gateway1% (
route delete 0.0.0.0/0
route add 0.0.0.0/0 %NHS_Gateway1% metric 10
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
)
IF DEFINED %NHS_Gateway2% (
route add 0.0.0.0/0 %NHS_Gateway2% metric 20
IF %ERRORLEVEL% NEQ 0 (Echo ERROR : Impossible to add the route, please check route print) else (Echo Route Add)
)
请阅读 Why is no string output with 'echo %var%' after using 'set var = text' on command line? 上的答案以了解为什么在批处理文件中将 1 个或多个 space 放在等号周围以将字符串分配给环境变量。
并阅读 this answer 解释批处理文件中 IF 条件的正确语法。在批处理文件中必须小心使用空格。在某些位置上需要 space,在其他位置上 space 通常是错误的。
并且必须注意在使用 (
... )
定义的块中引用环境变量的值,因为命令处理器使用 %variable%
替换对环境变量的所有引用在处理块中的行之前,通过它们在整个块中的值来语法。对于在块内定义或设置并在块内求值的环境变量,有必要启用延迟扩展并使用 !variable!
引用这些变量以使用延迟扩展。更好的是避免延迟环境变量扩展的需要。
goto 是 C/C++ 中很少使用的关键字。但在批处理文件中,它是一个非常重要的命令,它的使用使大多数批处理文件比使用 C/C++ 中使用的嵌套 IF 结构要容易得多,以避免使用 转到.
评估批处理文件的参数有一个通用规则:
如果没有定义第一个参数,则肯定没有更多的参数。
嗯,可以使用例如 "" "second parameter" ThirdParameter
调用批处理文件 运行 它带有 3 个参数,其中第一个是空字符串。但是对于您的脚本,可以将空字符串解释为根本未指定参数。
这是使用 goto 重新编码的批处理文件,避免了延迟扩展的需要。
@echo off
echo Network Home Script V0.1
setlocal
rem Default configuration
set "NHS_Network1=192.168.0.0/24"
set "NHS_Router1=192.168.0.254"
set "NHS_Network2=192.168.1.0/24"
set "NHS_Router2=192.168.1.1"
set "NHS_Gateway1=192.168.1.1"
set "NHS_Gateway2=192.168.0.254"
rem Run script with the defaults if executed without any
rem parameter or with just 1 parameter for first network.
if "%~1"=="" goto SetRoutes
if "%~2"=="" goto SetRoutes
rem IPv4 address with netmask and router address defined for network 1.
set "NHS_Network1=%~1"
set "NHS_Router1=%~2"
rem Delete all other by default defined environment variables.
set "NHS_Network2="
set "NHS_Router2="
set "NHS_Gateway1="
set "NHS_Gateway2="
if "%~3"=="" goto SetRoutes
if "%~4"=="" goto SetRoutes
rem IPv4 address with netmask and router address defined for network 2.
set "NHS_Network2=%~3"
set "NHS_Router2=%~4"
rem Set the gateway addresses if defined as fifth and sixth parameter.
if not "%~5"=="" set "NHS_Gateway1=%~5"
if not "%~6"=="" set "NHS_Gateway2=%~6"
:SetRoutes
rem The variables NHS_Network1 and NHS_Router1 are always defined.
%SystemRoot%\System32\route.exe delete %NHS_Network1%
%SystemRoot%\System32\route.exe add %NHS_Network1% %NHS_Router1%
if errorlevel 1 (
echo ERROR : Impossible to add route for network 1, please check route print.
) else (
echo Route for network 1 added.
)
rem NHS_Router2 is always defined if NHS_Network2 is defined.
if defined NHS_Network2 (
%SystemRoot%\System32\route.exe delete %NHS_Network2%
%SystemRoot%\System32\route.exe add %NHS_Network2% %NHS_Router2%
if errorlevel 1 (
echo ERROR : Impossible to add route for network 2, please check route print.
) else (
echo Route for network 2 added.
)
)
if defined NHS_Gateway1 (
%SystemRoot%\System32\route.exe delete 0.0.0.0/0
%SystemRoot%\System32\route.exe add 0.0.0.0/0 %NHS_Gateway1% metric 10
if errorlevel 1 (
echo ERROR : Impossible to add route for gateway 1, please check route print.
) else (
echo Route for gateway 1 added.
)
)
if defined NHS_Gateway2 (
%SystemRoot%\System32\route.exe add 0.0.0.0/0 %NHS_Gateway2% metric 20
if errorlevel 1 (
echo ERROR : Impossible to add route for gateway 2, please check route print.
) else (
echo Route for gateway 2 added.
)
)
endlocal
另请参阅 Microsoft 支持文章 Testing for a Specific Error Level in Batch Files。
if errorlevel 1
的用法 - 意味着如果先前命令或应用程序的退出代码大于或等于 1 - 优于在块中使用 %ERRORLEVEL%
作为命令处理器替换 %ERRORLEVEL%
在完全执行上面的行之前,已经根据此变量的当前值解析块。如果不使用特殊语法来检查错误级别,则有必要使用延迟扩展。
要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
endlocal /?
if /?
rem /?
route /?
set /?
setlocal /?
@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET args=%*
FOR %%a IN (NHS_Network1:192.168.0.0/24
NHS_Router1:192.168.0.254
NHS_Network2:192.168.1.0/24
NHS_Router2:192.168.1.1
NHS_Gateway1:192.168.1.1
NHS_Gateway2:192.168.0.254
) DO FOR /f "tokens=1,2delims=:" %%v IN ("%%a") DO (
FOR /f "tokens=1*" %%t IN ('echo !args!') DO (
IF "%%~t"=="" (SET "%%v=%%w") ELSE (SET "%%v=%%~t")
IF DEFINED args (SET "args=%%u") ELSE (SET "%%v=%%w")
)
)
SET nhs
GOTO :EOF
如果需要,可以添加其他数据 - 格式应该是显而易见的。
将 args
设置为提供给批处理的参数列表。
对于每个 varname:varvalue,将 %%v
分配给变量名并 %%w
默认值。
将变量设置为第一个剩余参数或默认值
如果还有剩余参数,请删除一个。否则,使用默认值。
与原版不完全相同,但可能有用。