Windows命令提示符:使用在单行的同一行中设置的变量

时间:2014-05-02 03:41:44

标签: windows batch-file syntax windows-7 cmd

好的,我了解到可以使用&&&将多个命令合并为一行,但似乎set的变量实际上并不可用用于在同一行中插值:

C:\Users\Andrew>set foo=hello, world!&& echo %foo%
%foo%

C:\Users\Andrew>echo %foo%
hello, world!

为什么我无法完成这项工作,有没有办法让它在单行中运作?

我需要一个单行的原因是我正在使用的外部程序接受一个命令作为预运行钩子,当然,我需要运行多个命令。


抢先防御

  1. " hello, world!应该用双引号包围!" 实际上,这样做似乎在变量中存储了双引号,我不想要,例如

    C:\Users\Andrew>set bar="hello, world!"&& echo %bar%
    %bar%
    
    C:\Users\Andrew>echo %bar%
    "hello, world!"
    
  2. " &&之前应该有一个空格!" 实际上,这样做似乎在变量中存储了一个尾随空格,我不想要,例如

    C:\Users\Andrew>set bar="hello, world!"&& echo %bar%
    %bar%
    
    C:\Users\Andrew>echo %bar%
    "hello, world!"
    
  3. "两者!" > :(

    C:\Users\Andrew>set mu="hello, world!" && echo %mu%
    %mu%
    
    C:\Users\Andrew>echo (%mu%)
    ("hello, world!" )
    

4 个答案:

答案 0 :(得分:9)

您可以在同一行中执行此操作,但我建议您使用 preHook.bat 等批处理文件。

作为一个班轮

set "mu=hello, world!" && call echo %^mu%

首先,您可以看到引号与您的不同。


原因如下:

set test1="quotes"
set "test2=no quotes" with comment

在第一个测试中,引号将是test1变量的一部分,以及最后一个引号后的所有字符。

在第二个测试中,它使用SET命令的扩展语法 所以内容将是no quotes,因为只使用了最后一个引用的内容;其余的将被删除。

为了回显变量内容,我使用call echo %^mu%,因为百分比扩展会在解析行时扩展它,然后再执行任何命令。

call命令稍后会执行,并重新启动解析器,当在命令行使用时,它使用与批解析器不同的扩展规则:一个空变量(在本例中为{{ 1}},在第一次)保持不变;但是,在下一个解析器阶段,%^mu%插入符将被删除。

在您的情况下,^也可以,但仅当call echo %mu%始终为空时。在行执行前mu有内容时,插入符变体也有效。

有关SO: How does the Windows Command Interpreter (CMD.EXE) parse scripts?解析器的更多信息 关于SO: Variable expansion

的变量扩展

答案 1 :(得分:6)

虽然我接受了@ jeb的回答,但我最终还是要走另一条路,因为我需要管道输出我的命令,而call这样做导致了错误的结果。实际上,call本身的文档备注,

  

请勿将管道和重定向符号与调用一起使用。

相反,@ Blorgbeard提醒我cmd的{​​{1}}选项(我相信它应该是小写的,而不是大写的),我意识到我可以简单地启动一个子进程:

/v

(出于某种原因,C:\Users\Andrew>cmd /v /c "set foo=hello, world!&& echo !foo!" hello, world! 必须出现在/v之前。)在引号中,我能够将输出传输到其他实用程序。对于那些采取这条道路的人来说,如果你发现自己需要在这些引号中使用引号,我建议完全避免它们并尝试使用字符代码,例如 /c对于空格,\x20表示双引号,等等。

例如,这是我问题的最终解决方案(警告:可能导致眼睛出血):

\x22

答案 2 :(得分:2)

尝试以下方法:

cmd.exe /v /c "set foo=hello, world & echo !foo!"

/v参数启用delayed variable expansion。这允许您访问变量' 执行时间的值,而不是解析时间(默认值)。您可以写!foo!而不是%foo%(打开此/v选项)来执行此操作。

您还可以通过注册表永久地转换延迟变量扩展,而不是传递/v,这显然会影响整个系统:

[HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor]
"DelayedExpansion"= (REG_DWORD)
1=enabled 0=disabled (default)

答案 3 :(得分:1)

我无法使用IF命令处理调用 cmd / v / c ,因此我想为可能需要它的人提供另一种选择: 使用FOR / F在单个命令中声明和使用变量。 例如:

FOR /F %i IN ('echo 123') DO (IF %i==123 echo done)

%i是使用IN命令的结果设置的变量,在此示例中为回声123'。

对于带单引号或空格的值,请使用" usebackq tokens = *"将命令放在反引号中的标志:

FOR /F "usebackq tokens=*" %i IN (`echo "hello, ' ' world!"`) DO (IF %i=="hello, ' ' world!" echo done)