我需要测试是否设置了一个变量。我尝试了几种技术,但每当%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,我更新了接受的答案,从使用括号到使用波浪号。每个人都说波浪更好,因为它更安全。我有点撕裂,因为波浪线看起来更复杂,不太清楚它的目的是什么,但尽管如此,我改变了它。


当前回答

总结一下:

set str=%~1
if not defined str ( echo Empty string )

如果%1为“”或“”或为空,此代码将输出“空字符串”。将其添加到目前不正确的公认答案中。

其他回答

从IF /?:

如果命令扩展是启用If 变更如下: IF [/I] string1 compare-op string2命令 IF CMDEXTVERSION编号命令 IF定义变量命令 ...... DEFINED条件刚好 像EXISTS一样,除了它需要一个 环境变量名称和返回值 如果环境变量为,则为 定义的。

我对网上的很多答案都有很多问题。大多数都适用于大多数情况,但总有一个极端情况会破坏每一个。 如果有引号,它可能不起作用,如果没有引号,它可能会中断,如果var有空格,则会出现语法错误,有些只对参数有效(而不是环境变量),其他技术允许一个空引号集作为“defined”传递,还有一些更棘手的技术不允许随后链接else。

这是一个我很满意的解决方案,如果你发现它不起作用的极端情况,请告诉我。

:ifSet
if "%~1"=="" (Exit /B 1) else (Exit /B 0)

在你的脚本中或在它自己的.bat中拥有子例程应该可以工作。 所以如果你想写(在pseudo中):

if (var)
then something
else somethingElse

你可以这样写:

(Call :ifSet %var% && (
    Echo something
)) || (
    Echo something else
)

它对我所有的测试都有效:

(Call :ifSet && ECHO y) || ECHO n
(Call :ifSet a && ECHO y) || ECHO n
(Call :ifSet "" && ECHO y) || ECHO n
(Call :ifSet "a" && ECHO y) || ECHO n
(Call :ifSet "a a" && ECHO y) || ECHO n

重复了n y n y y


更多的例子:

想看看是不是?调用:ifSet %var% && Echo set 如果不是(只有其他)呢?呼叫:ifSet %var% ||回声设置 检查传递的参数;工作很好。调用:ifSet %1 && Echo set 不想堵塞你的脚本/欺骗代码,所以你把它放在它自己的ifSet.bat?No problem:(调用ifSet.bat %var%) && Echo set) || (Echo未设置)

最好的半解决方案之一是将%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%防弹获取内容,你可以阅读如何接收甚至是最奇怪的命令行参数?

我通常用这个:

IF "%1."=="." GOTO MyLabel

如果%1为空,If将比较"."和".",结果为真。

你可以使用:

IF "%~1" == "" GOTO MyLabel

去掉外部的引号。一般来说,这是一种比使用方括号更可靠的方法,因为即使变量中有空格,它也能工作。