2011-02-10 153 views
72

我的操作系统是Windows Vista。我需要一个“.bat”文件,我需要检查用户是否输入任何命令行参数。如果那么如果参数等于-b那么我会做一些事情,否则我会标记“无效输入”。如果用户没有输入任何命令行参数,我会做一些事情。我创建了以下.bat文件。它适用于-b并且不等于-b个案 - 但在用户未传递任何命令行参数时失败。如何检查“.bat”文件中的命令行参数?

我总是得到错误:

GOTO was unexpected at this time. 

谁能告诉我,我究竟做错了什么?


ECHO OFF 
CLS 
ECHO. 

IF [%1]==[/?] GOTO BLANK 

IF %1=="-b" GOTO SPECIFIC 

IF NOT %1=="-b" GOTO UNKNOWN 

:SPECIFIC 

ECHO SPECIFIC 

GOTO DONE 

:BLANK 

ECHO No Parameter 

GOTO DONE 

:UNKNOWN 

ECHO Unknown Option 

GOTO DONE 

:DONE 

ECHO Done! 
+0

如果在其他两个IF语句中添加括号(如在'GOTO BLANK`行中),是否解决了这个问题? – 2011-02-10 04:00:05

回答

89

您需要检查的参数是空白:if "%~1"=="" goto blank

一旦你这样做,然后做一个-b的if/else开关:if "%~1"=="-b" (goto specific) else goto unknown

周边的带引号的参数可以更轻松地检查诸如空白/空白/缺失参数等内容。 “〜”确保如果双引号位于命令行参数中,则双引号将被剥离。

+0

这个工程!只有“其他”不被接受。我得到错误:'else'不被识别为内部或外部命令,可操作程序或批处理文件。所以我增加了另一个IF,用于“不等于-b”的情况。感谢你及时的答复。 – javauser71 2011-02-10 06:29:35

+5

ELSE必须与IF相同,或者必须直接放在括号后面 – jeb 2011-02-10 07:30:42

+4

如果%1包含空格,这似乎不适用于我,如果它是完整路径可执行文件。请参阅[Jeremiah Willcock的回答](http://stackoverflow.com/a/4953226/1840078),该解决方案即使对于值为空格的参数也适用。 – 2014-11-11 02:37:20

4

您正在比较字符串。如果省略参数,则%1会展开为空,因此命令变为IF =="-b" GOTO SPECIFIC(例如,这是语法错误)。用引号(或方括号)包装你的字符串。

REM this is ok 
IF [%1]==[/?] GOTO BLANK 

REM I'd recommend using quotes exclusively 
IF "%1"=="-b" GOTO SPECIFIC 

IF NOT "%1"=="-b" GOTO UNKNOWN 
6

除了其他的答案,这我同意,你可以考虑使用/I开关IF命令。

... the /I switch, if specified, says to do case insensitive string compares.

如果您想给用户提供不区分大小写的灵活性来指定参数,它可能会有所帮助。

IF /I "%1"=="-b" GOTO SPECIFIC 
7

简短的回答 - 用方括号:

if [%1]==[] goto :blank 

或(当你需要处理引用指定参数时,请参见下面的编辑):

if [%~1]==[] goto :blank 

为什么?你可能会问。那么,就像Jeremiah Willcock提到的那样:http://ss64.com/nt/if.html - 他们使用它!好的,但是报价有什么问题?

同样,简短的回答:它们是“神奇的” - 有时双(双)报价转换为单(双)报价。他们需要匹配,一开始。

考虑这个小脚本:

@rem argq.bat 
@echo off 

:loop 
if "%1"=="" goto :done 
echo %1 
shift 
goto :loop 

:done 
echo Done. 

测试一下:

C:\> argq bla bla 
bla 
bla 
Done. 

似乎工作。但现在,让我们切换到第二档:

C:\> argq "bla bla" 
bla""=="" was unexpected at this time. 

这没有评估为真,也没有评价它为false。脚本DIED。如果你应该关闭反应堆的某个地方,好运气。你现在会像Harry Daghlian一样死去。

您可能认为 - 好的,参数不能包含引号。如果他们这样做,就会发生。 错误下面是一些安慰:

C:\> argq ""bla bla"" 
""bla 
bla"" 
Done. 

哦,是的。别担心 - 有时候这个的工作。

让我们尝试另一个脚本:

@rem args.bat 
@echo off 

:loop 
if [%1]==[] goto :done 
echo %1 
shift 
goto :loop 

:done 
echo Done. 

你可以自己测试,它适用于上述情况确定。这是合乎逻辑的 - 引号与括号无关,所以这里没有魔法。但是用括号来激发参数呢?

D:\>args ]bla bla[ 
]bla 
bla[ 
Done. 

D:\>args [bla bla] 
[bla 
bla] 
Done. 

那里没有运气。方括号不能窒息cmd.exe的解析器。

让我们回到邪恶的引言片刻。 问题在那里,当参数以引号结束:

D:\>argq "bla1 bla2" 
bla2""=="" was unexpected at this time. 

如果我只是传递:

D:\>argq bla2" 
The syntax of the command is incorrect. 

该脚本将不会运行在所有。同为args.bat

D:\>args bla2" 
The syntax of the command is incorrect. 

但我得到的,什么时候" -characters数 “匹配”(即 - 为偶数),在这种情况下:

D:\>args bla2" "bla3 
bla2" "bla3 
Done. 

NICE - 我希望你学到了一些关于.bat文件如何拆分它们的命令行参数的东西(提示:*它不完全像bash中那样)。上面的参数包含一个空格。但报价不会自动剥离。

和argq?它对此有何反应?可以预见的是:

D:\>argq bla2" "bla3 
"bla3"=="" was unexpected at this time. 

所以 - 想你之前说:“?知道什么就用引号[因为,对我来说,这看起来更好]”。

编辑

近日,有关于这个答案的评论 - 好,sqare括号“无法处理”引用传递参数和对待他们就像如果他们没有报价。

语法:

if "%~1"=="" (...) 

是不是有些新发现凭借双引号的,但是从参数变量剥离报价的实用的功能的显示,如果第一个和最后一个字符是一个双引号。

这种“技术”的作品一样好与方括号:

if [%~1]==[] (...) 

正是指出这一点有益的事情,所以我也给予好评的新的答案。

最后,双引号的粉丝,你的书中是否存在形式为""的参数,还是空白?只是要求;)

2

其实,所有其他答案都有缺陷。最可靠的方法是:

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN) 

详解:

使用"%1"=="-b"将全力以赴崩溃,如果通过用空格和引号的说法。这是最不可靠的方法。

IF "%1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN) 

C:\> run.bat "a b" 

b""=="-b" was unexpected at this time. 

使用[%1]==[-b]是更好,因为它不会有空格和引号会崩溃,但如果参数用引号括起来它不会匹配。使用"%~1"=="-b"是最可靠的。如果它们存在,%~1将去掉周围的引号。所以它适用于和不用引号,也没有参数。

IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN) 

C:\> run.bat 
C:\> run.bat -b 
C:\> run.bat "-b" 
C:\> run.bat "a b" 

(all of the above tests work correctly)