在一个Windows CMD行中运行两个命令,其中一个命令是SET命令。

8

[目的]

这个简单的命令序列可以在Windows CMD Shell中正常运行:

dir & echo hello

这个命令会列出文件和目录,并输出字符串。

然而,下面的命令序列并不如我所预期地运行:

C:\Users\Administrator>set name=value & echo %name%
%name%

C:\Users\Administrator>echo %name%
value

C:\Users\Administrator>

我们可以看到,第一个回显无法获取环境变量。您能帮忙评论一下吗?我们将不胜感激!

注:操作系统为Windows 7 X64 Home Pre。


1
你的简单实验证明了Windows cmd行评估(与大多数shell程序一样)无法传播在同一处理行上进行的变量赋值。很高兴你只花了很少的时间就发现了这个“特性”/限制。除非你的cmd环境包含类似于Unix shell“eval”的东西,否则你必须将两个命令放在不同的行上,即set name=value新行echo %name%。祝你好运。 - shellter
2
@shellter - 不完全正确。虽然%name%在与set命令处于同一行时不会给出当前值,但延迟扩展将会有所不同。 - dbenham
1
@dbenham:感谢您提供的信息,我对Windows cmd还有很多不了解的地方。这就是为什么我把它留作评论的原因,而您的答案看起来非常全面。感谢分享。+1! - shellter
@shelter - 也许你现在应该删除你的不正确评论了? - user66001
2个回答

12

你的结果是因为%name%在解析阶段被展开,整行代码在值被设置之前被一次性解析。

你可以通过以下两种方式,在同一行中获取设置命令的当前值:

1)使用CALL命令使ECHO %NAME%再次解析:

set name=value&call echo %^name%

为了防止在执行该行之前已经定义了名称,我在百分号之间放置了一个^。如果没有这个字符,你将得到旧的值。

注意:你的原始代码中空格在&之前,这个空格会包含在变量的值中。你可以使用引号来避免额外的空格:set "name=value" &...

2) 使用延迟扩展在执行时获取值,而不是在解析时获取。大多数环境默认情况下不启用延迟扩展。你可以通过使用适当的CMD.EXE选项在命令行上启用延迟扩展。

cmd /v:on
set "name=value" & echo !name!

延迟扩展肯定可以在命令行上使用,但它更常用于批处理文件中。SETLOCAL 用于在批处理文件中启用延迟扩展(它不能从命令行工作)

setlocal enableDelayedExpansion
set "name=value" & echo !name!

非常感谢您的专业评论!第一个看起来非常优秀和简洁!因此我会选择第一个! :) - SOUser
2
注意:如果在批处理文件中使用上面的第一种解决方案,请使用第二种解决方案转义百分号,例如 set name=value&call echo %%name%% - user66001
зј–иҫ‘ - еңЁCALLи§ЈеҶіж–№жЎҲдёӯж·»еҠ ^пјҢд»ҘйҳІеҗҚз§°е·Із»Ҹе®ҡд№үдёәж—§еҖјгҖӮ - dbenham
这是一个与计数器相关的示例程序:set /a "count=count+1" & call echo 日期:%date% 时间:%time% __运行次数:%^count% - Tilo
在for循环中存在问题,我无法强制打印新时间,所有行都显示相同的时间。 for /L %i in (1,1,100) do (set myString=%time:~0,2%_%time:~3,2%_%time:~6,5%& call echo %^myString% & timeout 2) - Romasius
显示剩余2条评论

3

您还可以使用cmd /V /C(使用/V启用延迟扩展)。这对于在Windows cmd.exe中为一个命令设置环境变量非常好:

cmd /V /C "set "name=value" && echo !name!"
value

请注意在 set "name=value" 中使用双引号以避免在 value 后面出现额外的空格。
例如,不使用 双引号:
cmd /V /C "set name=value && echo '!name!'"
'value '

您需要考虑删除value&&之间的空格:
cmd /V /C "set name=value&& echo '!name!'"
'value'

但是使用双引号可以使赋值更加明确。


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