Windows 批处理文件中的连字符是什么意思?

Windows 批处理文件中的连字符是什么意思?

特别是,我无法理解下面几行中的连字符,它们来自维基百科

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%1if %1a==%1a惯例往往是[]

您可以使用引号、[] 或任何字符。但正如 supercat 在评论中指出的那样,在 %1 周围加引号不是一个好主意。(因为如果 %1 包含空格,用户会在传递给 %1 的内容中包含引号,如果 %1 中有空格,而在批处理文件中您在 %1 周围加上引号,则引号将取消,并且那里未加引号的空格将导致错误)。

如果您在命令行上执行 IF 并且不测试任何变量,那么您就没有 %1,甚至不需要 []。您会说IF "a b c"=="a b c" echo aIF 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-等。

天哪,我真不敢相信我还记得这些。:-) 我希望这会有所帮助!

相关内容