解析命令行参数时使用shift

时间:2014-10-04 00:12:40

标签: batch-file

C:\Temp> type test.bat
@echo off
setlocal EnableExtensions EnableDelayedExpansion
if "%~1" == "-c" (shift & set str=%1)
echo str = %str%
echo arg = %1


C:\Temp>test -c foo
str = -c
arg = foo

我预测上面的批处理文件会使用文本'foo'填充变量'str'。 但显然我错了。 我试图理解结果......是否会以某种方式延迟其影响?

将'shift'和'set'分隔成单独的行不会改变结果:

C:\Temp> type test.bat
if "%~1" == "-c" (
  shift
  set str=%1
)
echo str = %str%
echo arg = %1

C:\Temp> test.bat -c foo
str = -c
arg = foo

虽然下面的变体确实产生了我认为更可预测的输出:

C:\Temp> type test.bat
@echo off
setlocal EnableExtensions EnableDelayedExpansion
if "%~1" == "-c" shift
set str=%1
echo str = %str%

C:\Temp>test -c foo
str = foo

为什么班次似乎“延迟”了它的行为?

BTW:我正在尝试实现命名参数,例如像这样的东西:

REM Grab command-line parameters
:PARSE
if "%~1"=="" goto ENDPARSE
if "%~1"=="-c" set ipaddr=%1
if "%~1"=="-i" set iterations=%1
if "%~1"=="-s" set sleepTime=%1
if "%~1"=="-w" set window=%1
if "%~1"=="-l" set length=%1
if "%~1"=="-p" set port=%1
if "%~1"=="-d" set duration=%1
if "%~1"=="-b" set bandwidth=%1
if "%~1"=="-f" set output=%1
if "%~1"=="-d" set debug=%1
shift
goto PARSE
:ENDPARSE

3 个答案:

答案 0 :(得分:1)

啊 - delay - 这是关键字。搜索SO delayedexpansion。我从未尝试过!1,我怀疑它是否有效......

在块语句(a parenthesised series of statements)中,解析整个块并执行然后。块中的任何%var%将在解析块时被该变量的值替换 - 在块执行之前 - 同样的事情适用于{{1 }}

因此,FOR ... DO (block)将在遇到IF (something) else (somethingelse)时使用%variables%的值执行。

这同样适用于参数。在IF语句被解析时,%1%1的值替换,这就是为什么您没有看到if更改shift 1}}。

也许你可以尝试(我需要说这只是一行,你有很多......有些必要的事情)

if "%~1"=="-d" set debug=%2
shift
shift
goto parse

应该提供您所需要的。请注意,if /i ...会使if不区分大小写(如果需要)。

答案 1 :(得分:1)

这应该有效:它假设每个开关总会有一对项目

@echo off
REM Grab command-line parameters
:PARSE
if /i "%~1"=="-c" set "ipaddr=%~2"
if /i "%~1"=="-i" set "iterations=%~2"
if /i "%~1"=="-s" set "sleepTime=%~2"
if /i "%~1"=="-w" set "window=%~2"
if /i "%~1"=="-l" set "length=%~2"
if /i "%~1"=="-p" set "port=%~2"
if /i "%~1"=="-d" set "duration=%~2"
if /i "%~1"=="-b" set "bandwidth=%~2"
if /i "%~1"=="-f" set "output=%~2"
if /i "%~1"=="-d" set "debug=%~2"
shift
shift
if not "%~1"=="" goto :PARSE
echo "%ipaddr%"
echo "%iterations%"
echo "%sleepTime%"
echo "%window%"
echo "%length%"
echo "%port%"
echo "%duration%"
echo "%bandwidth%"
echo "%output%"
echo "%debug%"
pause

答案 2 :(得分:1)

啊,我明白了。我没有通过每个论点的立场清楚地思考。一旦我确定了我正在处理的标志(例如'-c',我就不想将%1(-c)分配给变量,而是分配给%2.然后我想要将标志和实际的标志都移开价值,有一个口吃的“轮班”

%0 = program name
%1 = -c 
%2 = foo

代码片段:

REM Grab command-line parameters
:PARSE
if "%~1"=="" goto ENDPARSE
if "%~1"=="-c" set ipaddr=%2
if "%~1"=="-i" set iterations=%2
if "%~1"=="-s" set sleepTime=%2
if "%~1"=="-w" set window=%2
if "%~1"=="-l" set length=%2
if "%~1"=="-p" set port=%2
if "%~1"=="-t" set duration=%2
if "%~1"=="-b" set bandwidth=%2
if "%~1"=="-o" set output=%2
if "%~1"=="-d" set debug=%2
shift
shift
goto PARSE
:ENDPARSE

感谢您的帮助,

- SK