我需要测试是否设置了一个变量。我尝试了几种技术,但每当%1被引号包围时,它们似乎都失败了,例如%1是“c:\一些带空格的路径”。

IF NOT %1 GOTO MyLabel // This is invalid syntax
IF "%1" == "" GOTO MyLabel // Works unless %1 has double quotes which fatally kills bat execution
IF %1 == GOTO MyLabel // Gives an unexpected GOTO error.

根据这个网站,这些是支持的IF语法类型。所以,我不知道该怎么做。

IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command

更新:在2020-10-25,我更新了接受的答案,从使用括号到使用波浪号。每个人都说波浪更好,因为它更安全。我有点撕裂,因为波浪线看起来更复杂,不太清楚它的目的是什么,但尽管如此,我改变了它。


当前回答

使用“IF DEFINED变量命令”测试批处理文件中的变量。

但如果您想测试批处理参数,请尝试以下代码以避免棘手的输入(如“1 2”或ab^>cd)

set tmp="%1"
if "%tmp:"=.%"==".." (
    echo empty
) else (
    echo not empty
)

其他回答

你可以使用

if defined (variable) echo That's defined!
if not defined (variable) echo Nope. Undefined.

最好的半解决方案之一是将%1复制到一个变量中,然后使用延迟展开,如delayedxp。对于任何内容总是安全的。

set "param1=%~1"
setlocal EnableDelayedExpansion
if "!param1!"=="" ( echo it is empty )
rem ... or use the DEFINED keyword now
if defined param1 echo There is something

这样做的好处是处理param1是绝对安全的。

param1的设置将在许多情况下工作,如

test.bat hello"this is"a"test
test.bat you^&me

但它仍然失败于一些奇怪的内容,比如

test.bat ^&"&

才能得到100%的正确答案

它检测%1是否为空,但对于某些内容,它无法获取内容。 这对于区分空%1和有""的%1也是有用的。 它使用CALL命令的能力在不中止批处理文件的情况下失败。

@echo off
setlocal EnableDelayedExpansion
set "arg1="
call set "arg1=%%1"

if defined arg1 goto :arg_exists

set "arg1=#"
call set "arg1=%%1"
if "!arg1!" EQU "#" (
    echo arg1 exists, but can't assigned to a variable
    REM Try to fetch it a second time without quotes
    (call set arg1=%%1)
    goto :arg_exists
)

echo arg1 is missing
exit /b

:arg_exists
echo arg1 exists, perhaps the content is '!arg1!'

如果你想100%防弹获取内容,你可以阅读如何接收甚至是最奇怪的命令行参数?

脚本1:

输入(“删除引号。”cmd"这是一个测试")

@ECHO OFF

REM Set "string" variable to "first" command line parameter
SET STRING=%1

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

REM IF %1 [or String] is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel


REM   OR   IF "." equals "." GOTO MyLabel
IF "%STRING%." == "." GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

PAUSE

输出(没有,%1不是空的,空的,或NULL):


使用上面的脚本运行("Remove Quotes.cmd"),不带任何参数

输出(%1为空白、空或NULL):

Welcome!

Press any key to continue . . .

注意:如果你在If () ELSE()语句中设置了一个变量,它将在退出If语句后才对DEFINED可用(除非“延迟变量扩展”被启用;一旦启用,请使用感叹号“!”来代替百分比“%”符号}。

例如:

脚本2:

输入(“删除引号。”cmd"这是一个测试")

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET STRING=%0
IF 1==1 (
  SET STRING=%1
  ECHO String in IF Statement='%STRING%'
  ECHO String in IF Statement [delayed expansion]='!STRING!'
) 

ECHO String out of IF Statement='%STRING%'

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

ECHO String without Quotes=%STRING% 

REM IF %1 is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

ENDLOCAL
PAUSE

输出:

C:\Users\Test>"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd" "This is a Test"  
String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is a Test"'  
String out of IF Statement='"This is a Test"'  
String without Quotes=This is a Test  

C:\Users\Test>  

注意:它还会从字符串中删除引号。

例如(使用脚本1或2): c:\ users \ test \ documents \批处理文件>"删除引号。cmd"这是"一个"测试"

输出(脚本2):

String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is "a" Test"'  
String out of IF Statement='"This is "a" Test"'  
String without Quotes=This is a Test  

在脚本2中不带任何参数地执行("Remove Quotes.cmd"):

输出:

Welcome!

Press any key to continue . . .

使用“IF DEFINED变量命令”测试批处理文件中的变量。

但如果您想测试批处理参数,请尝试以下代码以避免棘手的输入(如“1 2”或ab^>cd)

set tmp="%1"
if "%tmp:"=.%"==".." (
    echo empty
) else (
    echo not empty
)

不幸的是,我没有足够的声誉来评论或投票目前的答案,我不得不自己写。

最初OP的问题说的是“变量”而不是“参数”,这让人非常困惑,特别是因为这是谷歌中搜索如何测试空白变量的头号链接。自从我最初的答案以来,Stephan编辑了原始问题,以使用正确的术语,但我没有删除我的答案,而是决定留下它来帮助澄清任何困惑,特别是在谷歌仍然派人来这里寻找变量的情况下:

%1不是变量!它是一个命令行参数。

非常重要的区别。后面带数字的单个百分号表示命令行参数,而不是变量。

使用set命令设置变量,并使用2%符号(一个在前面,一个在后面)回收变量。例如%myvar%

要测试空变量,您可以使用“if not defined”语法(显式变量命令不需要任何百分号),例如:

set myvar1=foo  
if not defined myvar1 echo You won't see this because %myvar1% is defined.  
if not defined myvar2 echo You will see this because %myvar2% isn't defined.

(如果你想测试命令行参数,那么我建议参考jamesdlin的答案。)