有没有办法将参数解析为批处理脚本

有没有办法将参数解析为批处理脚本

我发现了一个非常有用的脚本这里它将解析批处理文件中的参数并按如下方式处理它们:

BatchFile.btm /a /b:22 /longopt Parm1 Parm2 /quotedArg:"long quoted arg"
   - OPTION_a will equal 1.
   - OPTION_b will equal 22
   - OPTION_quotedArg will equal "long quoted arg"
   - OPTION_longopt will eqal 1.
   - PARAM_1 will equal Parm1
   - PARAM_2 will equal Parm2
   - PARAM_0 will be set to the number of parms, so 2 in this case

但是,此脚本是为 .btm 文件编写的,似乎不适合 DOS 仿真器或较新版本的 Windows。有人可以翻译这个吗?或者知道在哪里可以找到可以在 Win7/Svr2003 中的 DOS 仿真器中运行的最新等效程序吗?

答案1

我已成功将此脚本的大部分内容转换为可在 Windows 7 批处理文件中运行。我尚未针对任何其他版本的 Windows 进行测试。

该程序扫描发送给它的命令行并设置与设置相对应的各种环境变量。

它为命令行上的每个参数设置一个 OPTION_arg 变量。如果是开关,则环境变量设置为 1。如果通过冒号给出值,则将其设置为该值。请注意,: [修改] 周围不能有任何空格,即使用括号括起来,此修改后的脚本也无法处理包含空格的选项或参数值。[/修改]

使用If defined OPTION_argif /i "%OPTION_arg%"=="value"测试选项

它还为输入的每个参数设置一个参数变量:PARAM_1PARAM_nPARAM_0一个包含 PARAM 数量的特殊值。适用于循环遍历所有 PARAM。例如for /l (1,1,%PARAM_0%) do ...

在批处理文件中调用 getopt 作为call GetOpt.bat %*

我还建议在主机批处理文件中设置setlocalendlocal,以便在主机批处理文件退出后选项和参数变量不会残留。

Example usage:  HostBatchFile.bat /a /b:22 /longopt Parm1 Parm2
   OPTION_a will equal 1.
   OPTION_b will equal 22
   OPTION_longopt will eqal 1.
   PARAM_1 will equal Parm1
   PARAM_2 will equal Parm2
   PARAM_0 will be set to the number of parms, so 2 in this case

我没有翻译的部分是:

  1. 结合任意类型的 DEBUG 标志进行屏幕输出
  2. 能够处理选项或参数的“带空格的字符串”,因为输入的参数的初始分隔是使用<SPACE>

这是翻译后的脚本。

@echo off
cls

set getopt_ParmCounter=1
set paramc=1
set DEBUG=1

set argc=0
for %%x in (%*) do Set /A argc+=1
echo Number of arguments: %argc%
echo %*&echo.

set _myvar=%*

rem Loop through all command line arguments one at a time
:varloop
set isparam=1
for /f "tokens=1*" %%a in ('echo %_myvar%') DO (
   set getopt_Parm=%%a
   set _myvar=%%b
   call :paramtype

   rem shift along arguments and rerun loop
   if NOT "%%b"=="" goto varloop
)
goto :eof

:paramtype
rem If first character starts with a - or / it must be an option
if /i "%getopt_Parm:~0,1%"=="-" call :option
if /i "%getopt_Parm:~0,1%"=="/" call :option 
if /i "%isparam%"=="1" call :param
goto :eof

:option
   set isparam=0
   rem Set the Equal Index to the position of the colon.  0 means none was found
   for /f %%j in ('findstring %getopt_Parm% :') do set getopt_EqIdx=%%j

   rem If the index is GE 0 then we must have a colon in the option.
   if /i "%getopt_EqIdx%"=="0" (call :nocolon) else (call :colon)
   goto :eof

      :colon
         rem set the OPTION value to the stuff to the right of the colon
         set /a getopt_ParmNameEnd=%getopt_EqIdx%-2
         call set getopt_ParmName=%%getopt_Parm:~1,%getopt_ParmNameEnd%%%
         call set getopt_ParmValue=%%getopt_Parm:~%getopt_EqIdx%%%
         set OPTION_%getopt_ParmName%=%getopt_ParmValue%
         goto :eof

      :nocolon
         rem This is a flag, so simply set the value to 1
         set getopt_ParmName=%getopt_Parm:~1%
         set getopt_ParmValue=1
         set OPTION_%getopt_ParmName%=%getopt_ParmValue%
         goto :eof

:param
   rem There was no / or - found, therefore this must be a paramater, not an option
   set PARAM_%getopt_ParmCounter%=%getopt_Parm%
   set PARAM_0=%getopt_ParmCounter%
   set /a getopt_ParmCounter+=1
   goto :eof

答案2

%*对于每个参数。您可能还会发现这些有用:

%0- 用于调用批处理文件的命令(可以是、、foo等)是第一个命令行参数,是第二个命令行参数, 依此类推(并且可以用于第 9 个之后的参数)。..\fooc:\bats\foo
%1
%2
%9SHIFT

%~nx0- 批处理文件的实际名称,无论调用方法如何(some-batch.bat)
%~dp0- 脚本的驱动器和路径(d:\scripts)
%~dpnx0- 是脚本的完全限定路径名(d:\scripts\some-batch.bat)

更多示例请访问http://www.ss64.com/nt/syntax-args.htmlhttp://www.robvanderwoude.com/parameters.html

来源:https://stackoverflow.com/questions/357315/get-list-of-passed-arguments-in-windows-batch-script-bat

答案3

批处理脚本语言不支持函数/过程,因此其模块化设计几乎不被提及,但你可以借助其setlocal[enabledelayedexpansion] / endlocal来实现它们。在这种机制下,模拟“参数”或“实参”并不太难,除了数组的返回,尤其是多个数组的返回。这里我实现了数组的返回,包括多个数组的返回。详情见下面的代码。当我用批处理搜索实现“getopt”时,我看到了上面的代码。下面的代码(/getopt.bat)是基于参考上面的代码编写的:

::
:://////////////////////////////////////////////////////////////////////////////
:: reference: https://superuser.com/questions/637133/is-there-a-way-to-parse-arguments-into-a-batch-script
::
@echo off


::
:://////////////////////////////////////////////////////////////////////////////
::
:getopt
    call :_getopt "%*" parmValueArr parmEndIdx optNameArr optValueArr optEndIdx
    set /a parmLastIdx=parmEndIdx-1 & set /a optLastIdx=optEndIdx-1
    set PARAM_0=!parmEndIdx!
    for /l %%a in (0,1,%parmLastIdx%) do (
        set /a "IdxAdd1=%%a+1"
        set PARAM_!IdxAdd1!=!parmValueArr[%%a]!
    )
    for /l %%a in (0,1,%optLastIdx%) do (
        set OPTION_NAME=OPTION_!optNameArr[%%a]!
        set !OPTION_NAME!=!optValueArr[%%a]!
    )
    goto :eof

::
:://////////////////////////////////////////////////////////////////////////////
::
:_getopt {%1 argvs_val[/in]} {%2 parmValueArr[/out]} {%3 parmEndIdx[/out]} {%4 optNameArr[/out]} {%5 optValueArr[/out]} {%6 optEndIdx[/out]}
    setlocal EnableDelayedExpansion
    set "parm2parse=%~1"
    set /a parmEndIdx=0
    set /a optEndIdx=0
    :__getopt_var_loop
    for /f "tokens=1*" %%a in ('echo %parm2parse%') do (
        set "getopt_parm=%%a"
        set "parm2parse=%%b"
        set "parmValue=" & set "optName=" & set "optValue="
        call :__getopt_param_type "!getopt_parm!" parmValue optName optValue
        if not "!parmValue!"=="" (
            set "%~2[!parmEndIdx!]=!parmValue!"
            set /a parmEndIdx+=1
        ) else (
            set "%~4[!optEndIdx!]=!optName!"
            set "%~5[!optEndIdx!]=!optValue!"
            set /a optEndIdx+=1
        )

        if NOT "!parm2parse!"=="" (
            goto :__getopt_var_loop
        )
    )
    set %~2[=MAKE_SURE_TO_ENTER_THE_LOOP
    set %~4[=MAKE_SURE_TO_ENTER_THE_LOOP
    set %~5[=MAKE_SURE_TO_ENTER_THE_LOOP
    set SubEnviron=1
    (
        for /F "tokens=1,2 delims==" %%a in ('set %~2[ 2^>nul') do (
            if defined SubEnviron (
                for /F "tokens=1,2 delims==" %%m in ('set %~4[ 2^>nul') do (
                    if defined SubEnviron (
                        for /F "tokens=1,2 delims==" %%w in ('set %~5[ 2^>nul') do (
                            if defined SubEnviron endlocal
                            set "%%w=%%x"
                        )
                    )
                    set "%%m=%%n"
                )
            )
            set "%%a=%%b"
        )
        set %~2[=
        set %~4[=
        set %~5[=
        if defined SubEnviron endlocal
        set "%~3=%parmEndIdx%"
        set "%~6=%optEndIdx%"
        endlocal & goto :eof
    )

::
:://////////////////////////////////////////////////////////////////////////////
::
:__getopt_param_type argv_val[/in] parmValue_var[/out] optName_var[/out] optValue_var[/out]
    setlocal EnableDelayedExpansion
    set "argv=%~1"
    set "first_char=%argv:~0,1%"
    set "isoption=false"
    if /i "%first_char%"=="-" set "isoption=true"
    if /i "%first_char%"=="/" set "isoption=true"
    if "%isoption%"=="true" (
        call :___getopt_option "%argv%" optName optValue
    ) else (
        call :___getopt_param "%argv%" parmValue
    )
    endlocal & set "%~2=%parmValue%" & set "%~3=%optName%" & set "%~4=%optValue%" & goto :eof

::
:://////////////////////////////////////////////////////////////////////////////
::
:___getopt_option opt[/in] optName[/out] optValue[/out]
    setlocal
    set "getopt_Parm=%~1"
    set "getopt_Parm=%getopt_Parm:~1%"
    for /f "tokens=1* delims=:" %%a in ("%getopt_Parm%") do (
        set "optName=%%a"
        set "optValue=1"
        if not "%%b"=="" (
            set "optValue=%%b"
        )
    )
    endlocal & set "%~2=%optName%" & set "%~3=%optValue%" & goto :eof

::
:://////////////////////////////////////////////////////////////////////////////
::
:___getopt_param parm[/in] parmValue[/out]
    setlocal
    endlocal & set "%~2=%~1" & goto :eof

::
:://////////////////////////////////////////////////////////////////////////////
::
:PrintArray [arrayName] [lowBound] [upBound]
    setlocal enabledelayedexpansion
    For /L %%C in (%2 1 %3) do echo ^<%1[%%C]=!%1[%%C]!^>
    endlocal & goto :eof

:://////////////////////////////// END /////////////////////////////////////////

测试用例如下(/getopt_test.bat):

@echo off

::
:://////////////////////////////// GETOPT_TEST_CASE0 ///////////////////////////
::
setlocal EnableDelayedExpansion
call getopt.bat /a /b:22 /longopt Parm1 Parm2
if not       "%OPTION_a%"=="1"     ( echo assert failed 01 )
if not       "%OPTION_b%"=="22"    ( echo assert failed 02 )
if not "%OPTION_longopt%"=="1"     ( echo assert failed 03 )
if not        "%PARAM_0%"=="2"     ( echo assert failed 04 )
if not        "%PARAM_1%"=="Parm1" ( echo assert failed 05 )
if not        "%PARAM_2%"=="Parm2" ( echo assert failed 06 )
endlocal

::
:://////////////////////////////// GETOPT_TEST_CASE1 ///////////////////////////
::
setlocal EnableDelayedExpansion
call getopt.bat /a /b:22 /longopt
if not       "%OPTION_a%"=="1"  ( echo assert failed 11 )
if not       "%OPTION_b%"=="22" ( echo assert failed 12 )
if not "%OPTION_longopt%"=="1"  ( echo assert failed 13 )
endlocal

::
:://////////////////////////////// GETOPT_TEST_CASE2 ///////////////////////////
::
setlocal EnableDelayedExpansion
call getopt Parm1 Parm2
if not "%PARAM_0%"=="2"     ( echo assert failed 21 )
if not "%PARAM_1%"=="Parm1" ( echo assert failed 22 )
if not "%PARAM_2%"=="Parm2" ( echo assert failed 23 )
endlocal

echo on & goto :eof

相关内容