使用MS批处理文件将程序的输出分配给变量


290

我需要使用MS批处理文件将程序的输出分配给变量。

因此,在GNU Bash shell中,我将使用VAR=$(application arg0 arg1)。我在Windows中使用批处理文件需要类似的行为。

有点像set VAR=application arg0 arg1

Answers:


433

一种方法是:

application arg0 arg1 > temp.txt
set /p VAR=<temp.txt

另一个是:

for /f %%i in ('application arg0 arg1') do set VAR=%%i

请注意,first %in %%i用来转义%after,当在批处理文件中而不是在命令行中使用上述代码时,需要使用first in 。想象一下,您test.bat有类似以下内容:

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%

11
这是一个很棒的技巧,我想知道为什么它不能在管道上工作
Bill K

25
这仅适用于单行文本的输出(第一个换行符后的后续行被省略)。
GroovyCakes,2015年

20
@Machta管道必须在括号中的表达式中以^符号转义。示例:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande

8
请勿与空格对齐。例如:对于('ver')中的/ f %% i,请设置VAR = %% i。如@Renat所写,应添加“ tokens = *”
Yura Shinkarev,2016年

2
@GroovyCakes关于重复输出的答案回答了关于输出中多行的问题
icc97

67

作为此先前答案的补充,可以在for语句内使用管道,并使用脱字符号进行转义:

    for /f "tokens=*" %%i in ('tasklist ^| grep "explorer"') do set VAR=%%i

1
两个要点:使用令牌捕获和插入符号以逃脱管道。
Christopher Oezbek

6
可在CLI上使用的等效版本,可以复制粘贴以简化修补程序:for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %i但是,通常,usebackq应使用来处理复杂的命令。
阿米特·奈杜

需要令牌来处理输出中的空间。
马克·英格拉姆'18

引号对我也适用,例如:for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i。如果命令本身没有引号,对我来说更容易。
保罗


8

假设您的应用程序的输出是数字返回码,则可以执行以下操作

application arg0 arg1
set VAR=%errorlevel%

5
不幸的是,输出是一个字符串。
firstZero10年

好。我将保留此名称以供后代使用,但请看@jdigital的链接,该链接讨论了将输出输出到临时文件的方法。
2010年

1
程序输出到stdout和stderr的输出与它的整数返回值不同。程序可以像上面的示例一样返回整数值,同时还可以将字符串发送到控制台(或重定向到文件或其他地方)。它们不是互斥的,而是两个不同的概念。
David Rector

7

执行中:for /f %%i in ('application arg0 arg1') do set VAR=%%i我遇到错误:%% i此时是意外的。作为解决方法,我必须执行以上操作for /f %i in ('application arg0 arg1') do set VAR=%i


9
在您需要%%的批处理文件中,以及在命令行上需要的批处理文件之外%
Jerry Jeremiah

2

除了答案之外,您不能在循环的设置部分中直接使用输出重定向运算符for(例如,如果您想隐藏用户的stderror输出并提供更好的错误消息)。相反,您必须使用脱字符号(^)对其进行转义:

for /f %%O in ('some-erroring-command 2^> nul') do (echo %%O)

参考:在批处理脚本的for循环中重定向命令的输出


1
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

REM Prefer backtick usage for command output reading:
REM ENABLEDELAYEDEXPANSION is required for actualized
REM  outer variables within for's scope;
REM within for's scope, access to modified 
REM outer variable is done via !...! syntax.

SET CHP=C:\Windows\System32\chcp.com

FOR /F "usebackq tokens=1,2,3" %%i IN (`%CHP%`) DO (
    IF "%%i" == "Aktive" IF "%%j" == "Codepage:" (
        SET SELCP=%%k
        SET SELCP=!SELCP:~0,-1!
    )
)
echo actual codepage [%SELCP%]

ENDLOCAL

(加号1)用于反引号的解释
桑德堡

1

您可以使用批处理宏来简单地捕获命令输出,就像bash shell的行为一样。

宏的用法很简单,看起来像

%$set% VAR=application arg1 arg2

它甚至适用于管道

%$set% allDrives="wmic logicaldisk get name /value | findstr "Name""

宏像数组一样使用变量,并将每一行存储在单独的索引中。
在示例中%$set% allDrives="wmic logicaldisk,将创建以下变量:

allDrives.Len=5
allDrives.Max=4
allDrives[0]=Name=C:
allDrives[1]=Name=D:
allDrives[2]=Name=F:
allDrives[3]=Name=G:
allDrives[4]=Name=Z:
allDrives=<contains the complete text with line feeds>

要使用它,了解宏本身的工作原理并不重要。

完整的例子

@echo off
setlocal

call :initMacro

%$set% ipOutput="ipconfig"
call :ShowVariable ipOutput
echo First line is %ipOutput[0]%

echo( 
%$set% driveNames="wmic logicaldisk get name /value | findstr "Name""
call :ShowVariable driveNames

exit /b

:ShowVariable
setlocal EnableDelayedExpansion
for /L %%n in (0 1 !%~1.max!) do (
    echo %%n: !%~1[%%n]!
)
echo(
exit /b

:initMacro
if "!!"=="" (
    echo ERROR: Delayed Expansion must be disabled while defining macros
    (goto) 2>nul
    (goto) 2>nul
)
(set LF=^
%=empty=%
)
(set \n=^^^
%=empty=%
)

set $set=FOR /L %%N in (1 1 2) dO IF %%N==2 ( %\n%
    setlocal EnableDelayedExpansion                                 %\n%
    for /f "tokens=1,* delims== " %%1 in ("!argv!") do (            %\n%
        endlocal                                                    %\n%
        endlocal                                                    %\n%
        set "%%~1.Len=0"                                            %\n%
        set "%%~1="                                                 %\n%
        if "!!"=="" (                                               %\n%
            %= Used if delayed expansion is enabled =%              %\n%
                setlocal DisableDelayedExpansion                    %\n%
                for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                if "!!" NEQ "" (                                    %\n%
                    endlocal                                        %\n%
                    )                                               %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set "line=%%O"                                      %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set pathExt=:                                       %\n%
                set path=;                                          %\n%
                set "line=!line:^=^^!"                              %\n%
                set "line=!line:"=q"^""!"                           %\n%
                call set "line=%%line:^!=q""^!%%"                   %\n%
                set "line=!line:q""=^!"                             %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") do (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") Do (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L" !                      %\n%
                        if %%C == 0 (                               %\n%
                            set "%%~1=%%~L" !                       %\n%
                        ) ELSE (                                    %\n%
                            set "%%~1=!%%~1!!LF!%%~L" !             %\n%
                        )                                           %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        ) ELSE (                                                    %\n%
            %= Used if delayed expansion is disabled =%             %\n%
            for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set "line=%%O"                                      %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") DO (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") DO (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L"                        %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        )                                                           %\n%
        set /a %%~1.Max=%%~1.Len-1                                  %\n%
)                                                                   %\n%
    ) else setlocal DisableDelayedExpansion^&set argv=

goto :eof

0

我编写了每5秒ping google.com并以当前时间记录结果的脚本。在这里,您可以找到变量“ commandLineStr”的输出(带有索引)

@echo off

:LOOPSTART

echo %DATE:~0% %TIME:~0,8% >> Pingtest.log

SETLOCAL ENABLEDELAYEDEXPANSION
SET scriptCount=1
FOR /F "tokens=* USEBACKQ" %%F IN (`ping google.com -n 1`) DO (
  SET commandLineStr!scriptCount!=%%F
  SET /a scriptCount=!scriptCount!+1
)
@ECHO %commandLineStr1% >> PingTest.log
@ECHO %commandLineStr2% >> PingTest.log
ENDLOCAL

timeout 5 > nul

GOTO LOOPSTART
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.