特别是,我无法理解下面几行中的连字符,它们来自维基百科
if not -%1-==-- echo Argument one provided
if -%1-==-- echo Argument one not provided & exit /b
要测试变量是否存在或定义,基本上有两种方法,这是我从中学到的这里:
IF DEFINED MyVar (ECHO MyVar IS defined) ELSE (ECHO MyVar is NOT defined)
IF "%MyVar%"=="" (ECHO MyVar is NOT defined) ELSE (ECHO MyVar IS defined)
那么,(1) %1 参数周围的连字符和 (2) == 符号后的连字符是什么意思?
答案1
考虑一下
C:\>if not -%1-==-- echo Argument one provided
Argument one provided
C:\>if not P%1P==PP echo Argument one provided
Argument one provided
显然,减号/连字符只是用来方便指定空值。该特定符号在该表达式中没有特殊含义 - 它被视为与任何其他非特殊字符一样。
我们可以添加空格,以便更清楚地表明==
操作符是不是被周围字符修改
C:\>if not P%1P == PP echo Argument one provided
Argument one provided
一般来说,最好使用更多人能够立即理解的常规方法(例如使用引号)。
C:\>if not "%1"=="" echo Argument one provided
Argument one provided
我认为在 DOS 和早期版本的 Windows 中,使用引号存在一些问题(我不记得了),导致人们以这种方式使用可打印字符。例如,我还没有尝试过 %1 包含引号的情况。
答案2
使用 %1 时,在其周围放置一些东西很重要,以防止批处理文件在 %1 为空时中断,因为 %1 不是变量,它会被值替换,就像 SQL 注入一样批量注入示例,当值为零,并且 %1 在 IF 中时,您将获得损坏的代码。if %1==""
变成 if == ""
并给出错误。
至于为什么如果定义对 %1 不起作用,%1 是值而不是变量,因此定义在那里不起作用。对于 %1 为空时有效的代码,您需要在 %1 被替换为空时不会中断的代码。尝试if "%1"==""
或尝试if [%1]==[]
说 -%1 确实看起来有点令人困惑,在我看来这不是一个好的惯例!从技术上讲,你甚至可以这样做,if a%1==a%1
但if %1a==%1a
惯例往往是[]
您可以使用引号、[] 或任何字符。但正如 supercat 在评论中指出的那样,在 %1 周围加引号不是一个好主意。(因为如果 %1 包含空格,用户会在传递给 %1 的内容中包含引号,如果 %1 中有空格,而在批处理文件中您在 %1 周围加上引号,则引号将取消,并且那里未加引号的空格将导致错误)。
如果您在命令行上执行 IF 并且不测试任何变量,那么您就没有 %1,甚至不需要 []。您会说IF "a b c"=="a b c" echo a
或 IF a==b echo a
如果在批处理文件中,那么您经常有 %1,而不是在 %1 周围使用引号,而是在它周围使用例如一个或两个字符例如[%1]
如果您需要保留空格并且它不是 %1 egeg IF [%1]==[a]
或IF [%1]==["a b"] echo a
不要这样做,"%1"
因为 %1 可能已经有引号,您的引号将取消它,然后如果 %1 有空格,您的 if 语句会中断。
如果您在命令行上测试变量,则取决于变量是否有引号。您可以查看内容。
变量可以有空格但不包含引号。
因此,在这个特定的命令行情况下,在 %a% 周围加上引号不会产生双引号,如果您想针对“a b”进行测试,则必须在 %a% 周围加上引号
C:\>set a=a b
C:\>echo %a%
a b
C:\>IF %a%=="a b" echo sdf
b=="a b" was unexpected at this time.
C:\>IF "%a%"=="a b" echo sdf
sdf
So ^^^ we want "%a%"
而如果 %a% 包含引号,情况就不同了
C:\>set a="a b"
C:\>echo %a%
"a b"
C:\>IF %a%=="a b" echo a
a
C:\>IF "%a%"=="a b" echo a
b""=="a b" was unexpected at this time.
C:\>
^^^^ So there we want %a% without quotes around it.
所以这完全取决于变量或参数是否包含引号。如果 %1 中有空格,那么它将包含引号。所以我们知道,如果我们将 %1 与“a b”进行比较,那么 w 不会执行“%1”。如果 %1 不包含引号,它就不会包含空格,所以我们不会执行“%1”。所以我认为你永远不会想执行“%1”。因此,如果 %1 包含空格,则 %1 内会有引号,并且空格将被保留。
我根据 supercat 的评论删除了以下内容。我在上面的帖子中添加了更多内容。
引号最好放在 %1 周围,而不是 [] 或一些字符,如 A 或 -,因为例如,如果你使用 [],那么它不会保留空格
C:\>如果 [dab]==[dab] 回显 sdf
a这时候是出乎意料的。
说if "d a b"
这样就行了。所以 比其他字符(例如或或if "%1"
)更好if [%1]
a%1a
-%1
答案3
不确定您是否完全理解,所以让我看看是否可以简化它。
假设您的批处理文件%1
在命令行上收到一个值,并且您想查看它是“cat”还是“dog”。您可以对此进行测试:
if %1 == cat goto CAT
if %1 == dog goto DOG
REM Default: Complain about no dog or cat
goto OOPS
:CAT
echo I'm a cat!
REM Successful, so skip to end
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo I didn't see a cat or dog!
REM This just falls through to the end
:END
%1
被替换为 cat 或 dog 的文本(假设为 dog),因此解释器实际上看到的是:
if dog == cat goto CAT
if dog == dog goto DOG
但是如果运行脚本的人没有在命令行中包含值,则解释器将看到以下内容:
if == cat goto CAT
if == dog goto DOG
这是不正确的语法,会产生错误。因此,惯例是先包含 1 个或多个字符,然后先测试是否没有变量,如下所示:
if %1* == * goto OOPS
REM If no value passed in, this is seen as if * == * which evaluates to true
if %1 == cat goto CAT
if %1 == dog goto DOG
goto END
:CAT
echo I'm a cat!
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo You were supposed to include a type of pet!
:END
如果%1
结果为无,则额外的字符仍然存在以保持语法正确。我使用*
,但引号或感叹号也很常见,例如"%1"
或%1!
,以及连字符,例如--%1
或-%1-
等。
天哪,我真不敢相信我还记得这些。:-) 我希望这会有所帮助!