如何从第N个位置获取批处理文件参数?

时间:2008-12-19 23:39:55

标签: windows batch-file

How to Pass Command Line Parameters in batch file之后如何通过完全指定参数来获取其余参数?我不想使用SHIFT,因为我不知道可能有多少参数,如果可以,我们希望避免计算它们。

例如,给定此批处理文件:

@echo off
set par1=%1
set par2=%2
set par3=%3
set therest=%???
echo the script is %0
echo Parameter 1 is %par1%
echo Parameter 2 is %par2%
echo Parameter 3 is %par3%
echo and the rest are %therest%

运行mybatch opt1 opt2 opt3 opt4 opt5 ...opt20会产生:

the script is mybatch
Parameter 1 is opt1
Parameter 2 is opt2
Parameter 3 is opt3
and the rest are opt4 opt5 ...opt20

我知道%*给出了所有参数,但我不是前三个(例如)。

4 个答案:

答案 0 :(得分:23)

以下是在不使用SHIFT的情况下执行此操作的方法:

@echo off

for /f "tokens=1-3*" %%a in ("%*") do (
    set par1=%%a
    set par2=%%b
    set par3=%%c
    set therest=%%d
)

echo the script is %0
echo Parameter 1 is %par1%
echo Parameter 2 is %par2%
echo Parameter 3 is %par3%
echo and the rest are %therest%

答案 1 :(得分:1)

以下代码使用shift,但它避免使用for解析命令行,并让命令行解释器执行此任务(请注意for不解析双引号正确地说,例如,参数集A B" "CA解释为3个参数B""Cfor,但是作为2个参数A,解释器B" "C;此行为可防止正确处理"C:\Program Files\"等引用路径参数:

@echo off

set "par1=%1" & shift /1
set "par2=%1" & shift /1
set "par3=%1" & shift /1

set therest=
set delim=

:REPEAT
if "%1"=="" goto :UNTIL
set "therest=%therest%%delim%%1"
set "delim= "
shift /1
goto :REPEAT
:UNTIL

echo the script is "%0"
echo Parameter 1 is "%par1%"
echo Parameter 2 is "%par2%"
echo Parameter 3 is "%par3%"
echo and the rest are "%therest%"
rem.the additional double-quotes in the above echoes^
    are intended to visualise potential whitespaces

%therest%中的其余参数可能与最初关于分隔符的方式不同(请记住命令行解释程序也会处理TAB,,;,{{1} } as delimiters以及所有组合),因为这里所有分隔符都被一个空格所取代。但是,将=传递给其他命令或批处理文件时,它将被正确解析。

到目前为止,我遇到的唯一限制适用于包含插入符%therest%的参数。其他限制(与^<>|&相关)适用于命令行解释器本身。

答案 2 :(得分:1)

@echo off
setlocal enabledelayedexpansion

set therest=;;;;;%*
set therest=!therest:;;;;;%1 %2 %3 =!

echo the script is %0
echo Parameter 1 is %1
echo Parameter 2 is %2
echo Parameter 3 is %3
echo and the rest are: %therest%

这适用于引用的参数和带有相同符号或逗号的参数,只要前三个参数没有这些特殊的分隔符字符。

示例输出:

test_args.bat "1 1 1" 2 3 --a=b "x y z"
Parameter 1 is "1 1 1"
Parameter 2 is 2
Parameter 3 is 3
and the rest are: --a=b "x y z"

这可以通过替换原始命令行%1 %2 %3中的%*来实现。前五个分号只是为了确保只替换这些%1 %2 %3的第一个分号。

答案 3 :(得分:1)

另一种选择:-)

其他一些答案没有处理引号,也没有处理参数之间的额外空格。免责声明:我没有很好地对此进行过测试。

这只是 %*shift ugg 之后没有更新的解决方法!

我从@Pavel-P 的技术开始将其实现为 POP。

  • 它依赖于批处理解析器去除多余的空格
  • 这取决于全局变量“Params”
  • ~ 删除引号——让您根据需要重新引用。如果您不想要,请删除 ~
:PopFirstParam
    @set varname=%~1
    @set %varname%=%~2
    @rem @echo %varname% = '!%varname%!'
    @if '%3' equ '' set Params=&goto :eof
    @call :popone %Params%
@goto :eof
:popone
    @set Params=;;;%*
    @set Params=!Params:;;;%1 =!
@goto :eof

用法:

@setlocal enabledelayedexpansion
@set Params=%*
@call :PopFirstParam P1 %Params%
@call :PopFirstParam P2 %Params%
@call :PopFirstParam P3 %Params%
@call :PopFirstParam P4 %Params%
@rem etc . . .

特别是我用它来选择性地异步运行命令:

@setlocal enabledelayedexpansion
@rem set variables that decide what to be run  . . . . 

@call :RunIfDefined doNum1 "Title 1"      mycmd1.exe     some  "params"   here
@call :RunIfDefined doNum2 "MyTitle 2"    mylongcmd2.exe some  "params"   here
@call :RunIfDefined doNum3 "Long Title 3" mycmd3.exe     some  "params"   here
@goto :eof

:RunIfDefined
    @set Params=%*
    @call :PopFirstParam DefineCheck %Params%
    @if not defined %DefineCheck% goto :eof
    
    @call :PopFirstParam WindowTitle %Params%
    @call :PopFirstParam Command %Params%
    @rem %Params% should now be the remaining params (I don't care about spaces here)
    @echo start "%WindowTitle%" "%Command%" %Params%
    @start "%WindowTitle%" "%Command%" %Params%
@goto :eof
C:\test> set doNum1=yes
C:\test> set doNum3=yes
C:\test> call dothings.bat

start "Title 1" "mycmd1.exe"     some  "params"   here
start "Long Title 3" "mycmd3.exe"     some  "params"   here

可惜DOS没有#include