在Windows批处理文件中,使用命令的结果设置变量的值

107

Bash 环境中,如果想要将变量的值设置为某个命令的结果,我通常会这样做:

var=$(command -args)

其中var是由命令command -args设置的变量。我可以通过$var访问该变量。

与几乎所有Unix shell兼容的更常规的方法是:

set var=`command -args`

话虽如此,我该如何在Windows批处理文件中使用命令结果设置变量的值?我尝试过:

set var=command -args

但是我发现var被设置为command -args而不是命令的输出。

6个回答

67

若要按照Jesse所述的方法进行操作,从Windows批处理文件中,您需要编写以下内容:

for /f "delims=" %%a in ('ver') do @set foobar=%%a 

但是,我建议在Windows系统上使用Cygwin,如果你习惯于Unix类型的脚本编程。


23
在命令提示符中使用for /f "delims=" %a in ('ver') do @set foobar=%a。在脚本文件中使用for /f "delims=" %%a in ('ver') do @set foobar=%%a - georg
一个轻量级的替代方案是 Gnu On Windows(https://github.com/bmatzelle/gow/wiki)。只需打开命令提示符并运行 bash。然后您就可以编写 bash 命令。您还可以执行 bash 脚本。 - Nathan
4
请注意,如果您的命令包含管道符号,则需要使用插入符号进行转义,例如:for /f "delims=" %%a in ('echo foobar^|sed -e s/foo/fu/') do @set foobar=%%a。 - yoyo

38

需要有一定的谨慎,因为Windows批处理命令:

for /f "delims=" %%a in ('command') do @set theValue=%%a

不具有与Unix shell语句相同的语义:

theValue=`command`

考虑命令执行失败的情况,导致出现错误。

在Unix shell版本中,“theValue”的赋值仍会发生,任何先前的值都将被替换为空值。

在Windows批处理版本中,是“for”命令处理错误,而“do”子句永远不会被执行--因此,“theValue”的任何先前值将被保留。

要在Windows批处理脚本中获得更多类似Unix的语义,请确保进行赋值:

set theValue=
for /f "delims=" %%a in ('command') do @set theValue=%%a

在将Unix脚本转换为Windows批处理文件时,如果未清除变量的值,则可能导致细微的错误。


2
感谢您解释Windows和*nix之间微妙的差别。 - Jeroen Wiert Pluimers
5
请记得转义 command 中的任何特殊字符;例如:for /f "delims=" %%a in ('command1 ^| command2') do set VAR=%%a - Bill_Stewart
@Bill_Stewart 你真是救了我的一天,我曾经以为将管道命令的输出分配给变量要困难得多。 - MrBrody

23

当我需要在批处理文件中获取数据库查询结果时,这就是我的方法:

sqlplus -S schema/schema@db @query.sql> __query.tmp
set /p result=<__query.tmp
del __query.tmp

关键在于第二行: "set /p" 使用"<"重定向运算符将"result"的值设置为"__query.tmp"文件中第一行(仅第一行)的值。


16

我见过的唯一方法是这样做:

for /f "delims=" %a in ('ver') do @set foobar=%a

ver是Windows的版本命令,在我的系统上运行会产生以下结果:

Microsoft Windows [Version 6.0.6001]

来源


2

这里有两种方法:

@echo off

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;;set "[[=>"#" 2>&1&set/p "&set "]]==<# & del /q # >nul 2>&1" &::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: --examples

::assigning chcp command output to %code-page% variable
chcp %[[%code-page%]]%
echo 1: %code-page%

::assigning whoami command output to %its-me% variable
whoami %[[%its-me%]]%
echo 2: %its-me%


::::::::::::::::::::::::::::::::::::::::::::::::::
;;set "{{=for /f "tokens=* delims=" %%# in ('" &::
;;set "--=') do @set ""                        &::
;;set "}}==%%#""                               &::
::::::::::::::::::::::::::::::::::::::::::::::::::

:: --examples

::assigning ver output to %win-ver% variable
%{{% ver %--%win-ver%}}%
echo 3: %win-ver%


::assigning hostname output to %my-host% variable
%{{% hostname %--%my-host%}}%
echo 4: %my-host%

脚本的输出:
1: Active code page: 65001
2: mypc\user
3: Microsoft Windows [Version 10.0.19042.1110]
4: mypc

说明:

1]&:: 结尾的部分是行末注释,可以忽略。我只是为了宏包含而放置了它们。

2] 行首的 ;; 将被忽略,因为 ; 是批处理脚本的标准分隔符。它被放在那里是为了提醒注释,并进一步增强宏定义的位置。

3] 使用的技术称为“宏”,它将命令分配给变量,当调用该变量时,执行该命令。

4] 第一个定义的宏包含两个部分:

set "[[=>"#" 2>&1&set/p "

并且

set "]]==<# & del /q # >nul 2>&1"

通过&分隔,可以在一行上定义它们。第一个将命令的输出重定向到文件#中,并添加set/p以开始使用set /p technique 读取文件。第二个宏使用<#完成set /p读取,然后删除文件。两个宏之间的文本是变量的名称。类似于set /p myVariable=<#

5] 第二个宏包含三个部分,扩展后只是一个for /f循环。可能有更优雅的方法来实现。


2
阅读了很多遍后,我仍然不确定哪部分只是装饰,哪部分是实际的命令。虽然我不明白这个例子是做什么的,但我相信它能够正常工作。如何开始解密这里写的内容?是否有任何Windows shell指南可以查找这里使用的命令? - wvxvw
2
@wvxvw - 我已添加了解释。 - npocmaka

0
Set "dateTime="
For /F %%A In ('powershell get-date -format "{yyyyMMdd_HHmm}"') Do Set "dateTime=%%A"
echo %dateTime%
pause

在此输入图像描述 官方微软文档,关于for命令


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