批处理文件和引用变量

Batch File and Quoting Variables

我正在处理一个批处理文件,我想知道,为什么有些变量周围有双引号,而其他变量没有,例如?

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

但是这个:

SET name="bob"

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

...提供开头的结论:

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

set "VAR=value"

(命令扩展名可以是 enabled/disabled cmd(在命令提示符 window 中键入 cmd /? 以获得帮助),或者仅在批处理文件中,setlocal(输入 setlocal /? 获取详细信息)。)


首先,让我们看一下在命令提示符 window 中键入 set /?(或 help set)时出现的帮助文本中提到的标准语法:

set VAR=value

这显然是将字符串 value 赋值给变量 VAR

这种语法的好处是:

  • 它在禁用命令扩展时也有效;
  • 变量值没有被引号包围(假设 value 本身不包含引号),所以只有一个地方需要处理它们,即在变量扩展期间(如 %VAR%"%VAR%",具体取决于手头的情况;这在组合字符串如 constant_%VAR%"constant_%VAR%" 时特别有用,它们将扩展为 constant_value"constant_value",因此您始终可以完全控制引号的位置;如果值包含封闭的 ""constant_%VAR% 将扩展为 constant_"value",这可能不会是你想要的字符串);

但是可能会出现一些问题:

  • 任何(不可见的)尾随白色-space 成为字符串值的一部分,因此如果命令行后跟单个 SPACE 字符, VAR 将携带值 valueSPACE;
  • 当您将此命令与另一个命令连接时,例如 set VAR=value & echo Text& 字符之前的 SPACE 成为值的一部分;你当然可以写 set VAR=value&echo Some text,但这很难读;
  • 如果value包含特殊字符,如^ & ( ) < > |,您可能 运行 遇到问题;例如,set VAR=1&2 会将 1 赋给 VAR,那么就会出现错误,因为 & 分隔了两个命令,而 2 不是有效命令;

你问题中第二个例子的语法非常相似:

set VAR="value"

这会将字符串 "value" 分配给 VAR,因此引号包含在值中。

优点是:

  • 它在禁用命令扩展时也有效;
  • value 中的特殊字符(如 ^ & 等)不会因为 "";
  • 而造成任何麻烦

但仍然:

  • 引号成为值的一部分,在许多情况下可能会令人不安;
  • 不需要的尾随白色-spaces(在最后一个"之后)仍然成为字符串值的一部分;
  • 再次使用 & 将此命令与另一个命令连接时,您必须省略 & 符号周围的 space;

现在,让我们检查一下您问题中第一个示例的语法:

set "VAR=value"

这会将 value 分配给 VAR。由于引号围绕着整个赋值表达式,因此在实际完成赋值之前将引号移除。

这有几个优点:

  • 引号不会成为变量值的一部分;
  • 任何(意外的)尾随白色-spaces 不会成为变量值的一部分;
  • 您可以使用 SPACE&SPACE 将它与另一个命令连接起来,无需任何不需要的 space 被附加到值;
  • value中的特殊字符(如^&等)没有问题;

但是有一个问题:

  • 需要启用命令扩展才能使用此语法;否则,会出现错误;

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

set "VAR="value""

这会将 "value" 分配给 VAR

优势:

  • 不需要的尾随白色-spaces(在最后一个"之后)不会成为变量值的一部分;
  • 您可以使用 SPACE&SPACE 将它与另一个命令连接起来,无需任何值中不需要的尾随 space;

缺点:

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

旁注:

永远不要在 set 命令行中将 space 放在等号周围,因为它们将成为变量名 and/or 值的一部分。例如,命令行

set VAR = value

set "VAR = value"

都将字符串值 SPACEvalue 分配给名为 VARSPACE[ 的变量=173=].