批处理文件和引用变量

10

我正在使用批处理文件,有些变量周围有双引号,而有些则没有,比如为什么会这样?

SET "keePass=%USERPROFILE%\KeePass\KeePass-2.31\KeePass.exe"

但是这个:
SET name="bob"

为什么第一个有双引号,但第二个没有?

4
在不考虑引号放置位置的情况下,去掉等号周围的空格!否则,它们将成为变量名和值的一部分。在第一个示例中,"" 不是变量值的一部分;在第二个示例中(假设您去掉了 "=" 周围的空格),它们是值的一部分;第一个示例是最佳实践,因为它避免了像 ^ 这样的某些特殊字符带来的问题... - aschipfl
@aschipfl - 我明白了,所以它用于特殊字符可能会成为问题的情况下? - user5910494
3
是的,但是还有更多的优点:您不会遇到尾随空格问题(因为结束引号"表示值已结束),而且可以与其他命令内联使用(例如,set "var=value" & echo some text),而不会在末尾产生不必要的空格... 我总是使用这种语法,这样您始终可以在扩展期间(像%var%"%var%",具体取决于用法)关注引号的位置... - aschipfl
1
此外,当比较变量(例如 if "%var%"=="value"if "%var1%"=="%var2%")时,如果其中一个变量可能为空,则在变量和值两侧加上双引号是很有用的。此外,当变量被设置为路径和文件名时,为避免空格问题,它们应始终被双引号包围引用(例如 copy "%aFile%" "%aPath%")。 - Wes Larson
1个回答

11

首先,假设您已启用了命令扩展(这是Windows命令提示符cmd的默认设置),最佳实践是使用以下set语法:

set "VAR=value"

(命令扩展可通过cmd启用/禁用(在命令提示符窗口中键入cmd /?以获取帮助),或仅在批处理文件中,通过setlocal启用/禁用(键入setlocal /?以获取详细信息)。)
首先,让我们查看在命令提示符窗口中键入set /?(或help set)时出现的帮助文本中提到的标准语法:
set VAR=value

这将显然把字符串value赋值给变量VAR
这种语法的好处是:
  • 当命令扩展被禁用时,它也可以工作;
  • 变量值没有被引号包围(假设value本身不包含引号),因此只有一个地方需要注意它们,即在变量扩展期间(如%VAR%"%VAR%",取决于具体情况;当组合字符串时特别有用,如constant_%VAR%"constant_%VAR%",它们将分别扩展为constant_value"constant_value",因此您始终对引号的放置有完全控制;如果值包含封闭的""constant_%VAR%将扩展为constant_"value",这可能不是您想要的字符串);
但也可能会出现一些问题:
  • 任何(看不见的)尾随空格都成为字符串值的一部分,因此如果命令行后跟着单个SPACE字符,VAR将携带值valueSPACE
  • 当您将此命令与另一个命令连接起来时,例如set VAR=value & echo Text,则&字符前的SPACE将成为值的一部分;当然,您可以编写set VAR=value&echo Some text,但这很难阅读;
  • 如果value包含特殊字符,如^ & ( ) < > |,则可能会遇到问题;例如,set VAR=1&2将向VAR分配1,然后会出现错误,因为&分隔两个命令,而2不是有效命令;

你问题中的第二个示例的语法非常相似:
set VAR="value"

这将字符串"value"分配给VAR,因此引号包含在值中。
优点是:
  • 即使命令扩展被禁用,它也能正常工作;
  • 由于有"",所以value中的特殊字符(如^ &等)不会造成任何问题;
但仍然存在以下问题:
  • 引号成为值的一部分,在许多情况下可能会产生干扰;
  • 最后一个"后面的不必要的尾随空格仍然成为字符串值的一部分;
  • 再次使用&连接此命令与另一个命令时,必须省略和&之间的空格;

现在,让我们检查你问题中第一个示例的语法:
set "VAR=value"

这会将value赋给VAR。由于引号放在赋值表达式的整个周围,因此它们在实际完成赋值之前被删除。

这有几个优点:

  • 引号不会成为变量值的一部分;
  • 任何(无意的)尾随空格都不会成为变量值的一部分;
  • 您可以使用SPACE&SPACE将其与另一个命令连接起来,而不会附加任何不需要的空格到值中;
  • 值中的特殊字符(如^ &等)不是问题;

但是有一个问题:

  • 必须启用命令扩展才能让这种语法工作;否则,将会出现错误;

最后,如果确实希望引号成为变量值的一部分(尽管我不建议这样做),也可以组合上述语法:

set "VAR="value""

这将"value"赋值给VAR

优点:

  • 不需要的尾随空格(在最后一个"之后)不会成为变量值的一部分;
  • 您可以使用SPACE&SPACE将其与另一个命令连接,而不会在值中产生任何不需要的尾随空格;

缺点:

  • 引号成为值的一部分,在许多情况下可能会引起麻烦;
  • 必须启用命令扩展才能使此语法正常工作;否则,会出现错误;
  • value中的特殊字符(如^ &等)可能会导致问题;这是因为命令解析器的工作方式:一旦遇到第一个",任何特殊字符都不再被识别,它们被视为文字字符;在下一个"之后,特殊字符识别重新激活,以此类推;请注意,在value本身包含任何引号时,这也是正确的;

附注:

set命令行中不要在等号周围放置空格,因为它们将成为变量名称和/或值的一部分。例如,命令行

set VAR = value

并且

set "VAR = value"

两者都将字符串值SPACEvalue分配给名为VARSPACE的变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接