使用可变数量的参数调用批处理文件

时间:2016-11-18 09:46:19

标签: windows batch-file command-line cmd command-line-arguments

基本上,下面的脚本可以以三种不同的方式使用: 打电话给foo

  1. .bat boot_up "path"
  2. .bat halt "path"
  3. .bat ssh "path" "command"
  4. 我不能保证路径或命令没有空格。

    当我使用foo.bat执行我的子程序ssh时,一切正常。相反,当我尝试调用子例程boot_uphalt时,会出现错误:

    ( was unexpected at this time.
    

    但是,如果我向boot_uphalt添加第三个参数,那么一切都会再次起作用。

    所以我的问题是,如何使用变量长度的参数来管理批处理文件的调用?

    :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
    

2 个答案:

答案 0 :(得分:5)

您的错误来源是) else if "%1"=="ssh" if not %3=="" ( - 当您未传递第三个参数时,您的代码会扩展为) else if "halt"=="ssh" if not =="" (,这是无效的语法。整个复合语句必须具有有效的语法,即使是不触发的分支也是如此。您必须确保比较的左侧至少有一个字符。通常使用封闭引号,因为它们可以防止像&|这样的毒字符,以及空格,逗号,等号,制表符等标记分隔符。

通常,在与命令行参数进行比较时应使用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

答案 1 :(得分:2)

您可以预处理您的参数以删除传递的引号,如下所示(我简化了您的代码以创建独立的测试)

@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"