如何检查“.bat”文件中的命令行参数?

时间:2011-02-10 03:52:27

标签: windows file batch-file cmd

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

我总是得到错误:

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!

7 个答案:

答案 0 :(得分:124)

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

完成后,然后在-b上执行if / else开关:if "%~1"=="-b" (goto specific) else goto unknown

使用引号包围参数可以更轻松地检查空白/空/缺少参数等内容。 “〜”确保双引号在命令行参数中被删除。

答案 1 :(得分:25)

查看http://ss64.com/nt/if.html的答案;命令为IF [%1]==[] GOTO NO_ARGUMENT或类似命令。

答案 2 :(得分:13)

简答 - 使用方括号:

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.

繁荣这没有评估为true,也没有评估为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.

但在这种情况下,当" - 字符数“匹配”(即 - 是偶数)时,我能得到什么:

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]==[] (...)

指出这一点是有用的,所以我也提出了新的答案。

最后,双引号粉丝,你的书中是否存在""形式的论点,还是空白?请问';)

答案 3 :(得分:8)

除了我订阅的其他答案之外,您可以考虑使用/I命令的IF开关。

  

... / I切换,如果指定,表示要进行不区分大小写的字符串比较。

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

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

答案 4 :(得分:5)

您正在比较字符串。如果省略了参数,%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

答案 5 :(得分:5)

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

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]更好,因为它不会因空格和引号而崩溃,但如果参数被引号括起来则不会匹配。

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

C:\> run.bat "-b"

(does not match, and jumps to UNKNOWN instead of SPECIFIC)

使用"%~1"=="-b"是最可靠的。 %~1会删除周围的引号(如果存在)。所以它可以使用和不使用引号,也可以不使用args。

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)

答案 6 :(得分:2)

我最近一直在努力在批处理文件中实现复杂的参数切换,因此这是我研究的结果。提供的答案都不是完全安全的,例如:

"%1"=="-?"如果参数用引号引起来(文件名等需要)将不匹配,或者如果参数用引号引起来并且有空格(在文件名中也经常出现),则会崩溃

@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
rem echo First parameter is %1
if "%1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat -?

starting parameter test...

Condition is true, param=-?

C:\>test.bat "-?"

starting parameter test...

Condition is false, param="-?"

如果参数用引号引起来,则任何带有方括号[%1]==[-?][%~1]==[-?]的组合都将失败:

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if [%~1]==[-?] (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat "long file name"

starting parameter test...

First parameter is "long file name"
file was unexpected at this time.

建议的最安全的解决方案"%~1"=="-?"将使用复杂的参数崩溃,该参数包括引号外的文本和引号内的空格的文本:

@ECHO OFF
SETLOCAL 
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if "%~1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)

C:\>test.bat -source:"long file name"

starting parameter test...

First parameter is -source:"long file name"
file was unexpected at this time.

确保涵盖以上所有方案的唯一方法是使用EnableDelayedExpansion并使用变量按引用(而不按值)传递参数。然后,即使是最复杂的情​​况也可以正常工作:

@ECHO OFF
SETLOCAL EnableDelayedExpansion
echo.
echo starting parameter test...
echo.
echo First parameter is %1
:: we assign the parameter to a variable to pass by reference with delayed expansion
set "var1=%~1"
echo var1 is !var1!
:: we assign the value to compare with to a second variable to pass by reference with delayed expansion
set "var2=-source:"c:\app images"\image.png"
echo var2 is !var2!
if "!var1!"=="!var2!" (echo Condition is true, param=!var1!) else (echo Condition is false, param=!var1!)
C:\>test.bat -source:"c:\app images"\image.png

starting parameter test...

First parameter is -source:"c:\app images"\image.png
var1 is -source:"c:\app images"\image.png
var2 is -source:"c:\app images"\image.png
Condition is true, param=-source:"c:\app images"\image.png

C:\>test.bat -source:"c:\app images"\image1.png

starting parameter test...

First parameter is -source:"c:\app images"\image1.png
var1 is -source:"c:\app images"\image1.png
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images"\image1.png

C:\>test.bat -source:"c:\app images\image.png"

starting parameter test...

First parameter is -source:"c:\app images\image.png"
var1 is -source:"c:\app images\image.png"
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images\image.png"