使用可变数量的参数调用批处理文件
Call batch file with variable number of arguments
基本上,下面的脚本可以用三种不同的方式使用:
调用 foo
.bat boot_up "path"
.bat halt "path"
.bat ssh "path" "command"
我不能保证路径或命令没有空格。
当我使用 foo.bat 执行子程序 ssh
时,一切正常。相反,当我尝试调用我的子例程 boot_up
或 halt
时,出现错误:
( was unexpected at this time.
但是,如果我向 boot_up
或 halt
添加第三个参数,那么一切都会再次正常。
所以我的问题是,如何管理参数长度可变的批处理文件的调用?
:main
echo Argument 1: (%1)
echo Argument 2: (%2)
echo Argument 3: (%3)
call :set_cygwin_env || exit /b 1
if not "%1"=="" if not %2=="" (
if "%1"=="boot_up" (
call :boot_up %2
) else if "%1"=="halt" (
call :halt %2
) else if "%1"=="ssh" if not %3=="" (
call :ssh %2 %3
) else (
call :show_help || exit /b 1
)
) else (
call :show_help || exit /b 1
)
:exit
您可以预处理您的参数以删除传递的引号,如下所示(我简化了您的代码以创建独立测试)
@echo off
:main
set ARG1=%1
set ARG2=%2
set ARG3=%3
if x%ARG1%==x goto skarg1
if ^%ARG1:~0,1%==^" set ARG1=%ARG1:~1,-1%
:skarg1
if x%ARG2%==x goto skarg2
if ^%ARG2:~0,1%==^" set ARG2=%ARG2:~1,-1%
:skarg2
if x%ARG3%==x goto skarg3
if ^%ARG3:~0,1%==^" set ARG3=%ARG3:~1,-1%
:skarg3
echo Argument 1: (%ARG1%)
echo Argument 2: (%ARG2%)
echo Argument 3: (%ARG3%)
if "%ARG1%"=="boot_up" if not "%ARG2%"=="" (
echo bootup "%ARG2%"
)
:exit
- 如果参数为空,保持原样
- 如果参数以引号开头,只需删除第一个和最后一个字符
- 从现在开始使用
%ARGx%
(引用)代替 %1
、%2
仅使用参数 2 进行快速测试:
L:\>args boot_up
Argument 1: (boot_up)
Argument 2: ()
Argument 3: ()
L:\>args boot_up arg2
Argument 1: (boot_up)
Argument 2: (arg2)
Argument 3: ()
bootup "arg2"
L:\>args boot_up "arg2 space"
Argument 1: (boot_up)
Argument 2: (arg2 space)
Argument 3: ()
bootup "arg2 space"
L:\>args boot_up "arg2"
Argument 1: (boot_up)
Argument 2: (arg2)
Argument 3: ()
bootup "arg2"
您的错误来源是 ) else if "%1"=="ssh" if not %3=="" (
- 如果您不传递第三个参数,您的代码将扩展为 ) else if "halt"=="ssh" if not =="" (
,这是无效语法。整个复合语句必须具有有效的语法,即使是不触发的分支也是如此。您必须确保比较的左侧至少有一个字符。通常使用引号括起来,因为它们可以防止 &
和 |
等有害字符以及 space、逗号、等号、制表符等标记定界符。
通常,在与命令行参数进行比较时,您应该使用 if "%~1"=="someValue" ...
。 ~
删除所有现有的引号,然后您明确添加自己的引号。首先删除引号很重要,因为您无法预料用户是否添加了自己的引号。可以传入像 "this&that"
这样的值,因此 "%1"
将扩展为 ""this&that""
,而 &
将不再被引用。 "%~1"
扩展为所需的 "this&that"
。这个策略不是万无一失的,但它在不做你可能不想做的 crazy batch programming 的情况下就已经很好了。
所以你的固定代码应该是这样的
:main
echo Argument 1: (%1)
echo Argument 2: (%2)
echo Argument 3: (%3)
call :set_cygwin_env || exit /b 1
if not "%~1"=="" if not "%~2"=="" (
if "%~1"=="boot_up" (
call :boot_up %2
) else if "%~1"=="halt" (
call :halt %2
) else if "%~1"=="ssh" if not "%~3"=="" (
call :ssh %2 %3
) else (
call :show_help || exit /b 1
)
) else (
call :show_help || exit /b 1
)
:exit
基本上,下面的脚本可以用三种不同的方式使用: 调用 foo
.bat boot_up "path"
.bat halt "path"
.bat ssh "path" "command"
我不能保证路径或命令没有空格。
当我使用 foo.bat 执行子程序 ssh
时,一切正常。相反,当我尝试调用我的子例程 boot_up
或 halt
时,出现错误:
( was unexpected at this time.
但是,如果我向 boot_up
或 halt
添加第三个参数,那么一切都会再次正常。
所以我的问题是,如何管理参数长度可变的批处理文件的调用?
:main
echo Argument 1: (%1)
echo Argument 2: (%2)
echo Argument 3: (%3)
call :set_cygwin_env || exit /b 1
if not "%1"=="" if not %2=="" (
if "%1"=="boot_up" (
call :boot_up %2
) else if "%1"=="halt" (
call :halt %2
) else if "%1"=="ssh" if not %3=="" (
call :ssh %2 %3
) else (
call :show_help || exit /b 1
)
) else (
call :show_help || exit /b 1
)
:exit
您可以预处理您的参数以删除传递的引号,如下所示(我简化了您的代码以创建独立测试)
@echo off
:main
set ARG1=%1
set ARG2=%2
set ARG3=%3
if x%ARG1%==x goto skarg1
if ^%ARG1:~0,1%==^" set ARG1=%ARG1:~1,-1%
:skarg1
if x%ARG2%==x goto skarg2
if ^%ARG2:~0,1%==^" set ARG2=%ARG2:~1,-1%
:skarg2
if x%ARG3%==x goto skarg3
if ^%ARG3:~0,1%==^" set ARG3=%ARG3:~1,-1%
:skarg3
echo Argument 1: (%ARG1%)
echo Argument 2: (%ARG2%)
echo Argument 3: (%ARG3%)
if "%ARG1%"=="boot_up" if not "%ARG2%"=="" (
echo bootup "%ARG2%"
)
:exit
- 如果参数为空,保持原样
- 如果参数以引号开头,只需删除第一个和最后一个字符
- 从现在开始使用
%ARGx%
(引用)代替%1
、%2
仅使用参数 2 进行快速测试:
L:\>args boot_up
Argument 1: (boot_up)
Argument 2: ()
Argument 3: ()
L:\>args boot_up arg2
Argument 1: (boot_up)
Argument 2: (arg2)
Argument 3: ()
bootup "arg2"
L:\>args boot_up "arg2 space"
Argument 1: (boot_up)
Argument 2: (arg2 space)
Argument 3: ()
bootup "arg2 space"
L:\>args boot_up "arg2"
Argument 1: (boot_up)
Argument 2: (arg2)
Argument 3: ()
bootup "arg2"
您的错误来源是 ) else if "%1"=="ssh" if not %3=="" (
- 如果您不传递第三个参数,您的代码将扩展为 ) else if "halt"=="ssh" if not =="" (
,这是无效语法。整个复合语句必须具有有效的语法,即使是不触发的分支也是如此。您必须确保比较的左侧至少有一个字符。通常使用引号括起来,因为它们可以防止 &
和 |
等有害字符以及 space、逗号、等号、制表符等标记定界符。
通常,在与命令行参数进行比较时,您应该使用 if "%~1"=="someValue" ...
。 ~
删除所有现有的引号,然后您明确添加自己的引号。首先删除引号很重要,因为您无法预料用户是否添加了自己的引号。可以传入像 "this&that"
这样的值,因此 "%1"
将扩展为 ""this&that""
,而 &
将不再被引用。 "%~1"
扩展为所需的 "this&that"
。这个策略不是万无一失的,但它在不做你可能不想做的 crazy batch programming 的情况下就已经很好了。
所以你的固定代码应该是这样的
:main
echo Argument 1: (%1)
echo Argument 2: (%2)
echo Argument 3: (%3)
call :set_cygwin_env || exit /b 1
if not "%~1"=="" if not "%~2"=="" (
if "%~1"=="boot_up" (
call :boot_up %2
) else if "%~1"=="halt" (
call :halt %2
) else if "%~1"=="ssh" if not "%~3"=="" (
call :ssh %2 %3
) else (
call :show_help || exit /b 1
)
) else (
call :show_help || exit /b 1
)
:exit