我的操作系统是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!
答案 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"