Windows 如何检查";中的命令行参数;。bat";文件

Windows 如何检查";中的命令行参数;。bat";文件,windows,file,batch-file,cmd,Windows,File,Batch File,Cmd,我的操作系统是WindowsVista。我需要一个“.bat”文件,在这里我需要检查用户是否输入了任何命令行参数。如果是,则如果参数等于-b,则我将执行其他操作,否则我将标记“无效输入”。若用户并没有输入任何命令行参数,那个么我将做一些事情。我创建了以下.bat文件。它适用于-b,不等于-b情况,但当用户未传递任何命令行参数时,它将失败 我总是会出错: GOTO was unexpected at this time. 谁能告诉我我做错了什么 您需要检查参数是否为空:如果“%~1”==”转到

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

我总是会出错:

GOTO was unexpected at this time.
谁能告诉我我做错了什么



您需要检查参数是否为空:
如果“%~1”==”转到空

完成此操作后,在-b:
上执行if/else开关,如果“%~1”==“-b”(转到特定位置)else转到未知位置


在参数周围加引号可以更容易地检查空白/空/缺少的参数。“~”确保如果双引号位于命令行参数上,则它们将被删除。

查看答案;如果[%1]=[]转到无参数或类似参数,则该命令为

您正在比较字符串。如果省略了参数,
%1
将扩展为空白,因此命令将变为
If==“-b”转到特定的
(例如,这是一个语法错误)。将字符串用引号(或方括号)括起来


除了我订阅的其他答案之外,您可以考虑使用<代码> /i>代码>开关> < <代码>命令> < /p> 。。。如果指定了/I开关,则表示to do不区分大小写的字符串比较

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

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

简短回答-使用方括号:

if [%1]==[] goto :blank
if [%~1]==[] (...)
或者(当您需要处理带引号的参数时,请参见下面的编辑):

为什么??你可能会问。嗯,正如杰里米·威尔科克所提到的:-他们用这个!好的,但是引号有什么问题吗

同样,简短的回答是:它们是“神奇的”——有时双引号会转换成单引号。首先,他们需要匹配

考虑一下这个小脚本:

@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.
Boom这没有评估为真,也没有评估为假。剧本死了。如果你想在线路的某个地方关闭反应堆,那就太倒霉了。你现在会像哈里·达格利安一样死去

你可能会想-好吧,参数不能包含引号。如果他们这样做,这种情况就会发生错了这里有一些安慰:

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.
您可以测试自己,它在上述情况下正常工作。这是合乎逻辑的-引号与括号无关,所以这里没有魔力。但是用括号把arg加上怎么样

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.
脚本根本不会运行。与参数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]==[] goto :blank
if [%~1]==[] (...)
指出这一点很有用,因此我也支持新的答案


最后,双引号粉丝们,你的书中是否存在形式为
的论点,还是空白的?只是问一下“;)

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

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
将去掉周围的引号(如果存在)。因此它可以使用引号和不使用引号,也可以不使用参数

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)

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

“%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.
确保涵盖上述所有场景的唯一方法是使用变量并通过引用(而不是通过值)传递参数。这样即使是最复杂的场景也可以正常工作:

@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"
如果你加上brac
@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.
@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"