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

Batch file 使用MS批处理文件将程序的输出分配给变量,batch-file,cmd,variable-assignment,windows-console,Batch File,Cmd,Variable Assignment,Windows Console,我需要使用MS批处理文件将程序的输出分配给变量 因此,在GNUBash shell中,我将使用VAR=$(应用程序arg0 arg1)。我需要在Windows中使用批处理文件进行类似操作 类似于set VAR=application arg0 arg1假设应用程序的输出是一个数字返回码,则可以执行以下操作 application arg0 arg1 set VAR=%errorlevel% @OP,如果程序输出的不是数字,则可以使用捕获程序的返回状态。一种方法是: application ar

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

因此,在GNUBash shell中,我将使用
VAR=$(应用程序arg0 arg1)
。我需要在Windows中使用批处理文件进行类似操作


类似于
set VAR=application arg0 arg1

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

application arg0 arg1
set VAR=%errorlevel%
@OP,如果程序输出的不是数字,则可以使用捕获程序的返回状态。一种方法是:

application arg0 arg1 > temp.txt
set /p VAR=<temp.txt
请注意,
%%i
中的第一个
%%
用于转义后面的
%%
,并且在批处理文件中而不是在命令行中使用上述代码时需要转义。想象一下,您的
test.bat
有如下功能:

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%
除此之外,管道还可以在for语句中使用,并通过插入符号转义:

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

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


参考:

执行时:
对于('application arg0 arg1')中的/f%%i,do set VAR=%%i
我收到错误:%%i此时是意外的。
作为修复,我必须在('application arg0 arg1')do set VAR=%i中为/f%i执行上面的
,我编写了脚本,每5秒ping google.com一次,并用当前时间记录结果。在这里可以找到变量“commandLineStr”(带索引)的输出


您可以使用批处理宏来简单地捕获命令输出,有点像bashshell的行为

宏的用法很简单,如下所示

%$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

::::: ---- defining the assign macro ---- ::::::::
setlocal DisableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

::set argv=Empty
set assign=for /L %%n in (1 1 2) do ( %\n%
   if %%n==2 (%\n%
      setlocal enableDelayedExpansion%\n%
      for /F "tokens=1,2 delims=," %%A in ("!argv!") do (%\n%
         for /f "tokens=* delims=" %%# in ('%%~A') do endlocal^&set "%%~B=%%#" %\n%
      ) %\n%
   ) %\n%
) ^& set argv=,

::::: -------- ::::::::


:::EXAMPLE
%assign% "WHOAMI /LOGONID",result
echo %result%
FOR/F宏 不像上一个宏那样容易阅读

::::::::::::::::::::::::::::::::::::::::::::::::::
;;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%
使用临时文件的宏 更容易阅读,如果你有一个SSD驱动器,它不会那么慢,但它仍然会创建一个临时文件

@echo off

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

chcp %[[%code-page%]]%
echo ~~%code-page%~~

whoami %[[%its-me%]]%
echo ##%its-me%##
@echo关闭
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;设置“[[=>”#“2>和1&set/p”&set”]==nul 2>和1&
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
chcp%[[%代码页%]]%
echo~~%代码页%~~
whoami%[%its me%]]%
echo##是我%##

不幸的是,输出是一个字符串。好的。我将为子孙后代保留此内容,但请看一下@jdigital的链接,它讨论如何将输出管道化到临时文件。程序输出到stdout和stderr的值与它的整数返回值不同。程序既可以像上面的示例中那样返回整数值,也可以发送string到控制台(或重定向到文件或其他地方)。它们不是相互排斥的,是两个不同的概念。这是一个很好的技巧,我想知道为什么它不能与管道一起工作。这只适用于作为单行文本的输出(第一行中断后省略后续行)@Machta管道必须在parens中的表达式中用^号转义。例如:
for/f“tokens=3”%%i in('route print^ | findstr“\”)do set“myVar=%%i”
不适用于带空格的行。例如/f%%i in('ver')do set VAR=%i。如@Renat所述,应添加“tokens”=*“@GroovyCakes您关于输出中多行的问题可以通过重复问题的回答两个要点:使用标记捕获和插入以跳出管道。在CLI上工作并且可以复制粘贴以便于修补的等效版本:
for/f”标记=*%i in('tasklist^ findstr explorer'))do@echo%i
但是一般来说,
usebackq
应该用来处理复杂的命令。需要标记来处理输出中的空格。引号对我也很有效,如下所示:
for/f“Tokens=*”%%i in(“'tasklist | grep explorer')do set VAR=%%i
。如果命令本身没有引号,对我来说就更容易了。在批处理文件中,您需要
%%
,在命令行上的批处理文件外部,您需要
%%
(plus1)来解释反勾号这是否回答了您的问题?
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
c:\>doskey assign=for /f "tokens=1,2 delims=," %a in ("$*") do @for /f "tokens=* delims=" %# in ('"%a"') do @set "%b=%#"

c:\>assign WHOAMI /LOGONID,my-id

c:\>echo %my-id%
@echo off

::::: ---- defining the assign macro ---- ::::::::
setlocal DisableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

::set argv=Empty
set assign=for /L %%n in (1 1 2) do ( %\n%
   if %%n==2 (%\n%
      setlocal enableDelayedExpansion%\n%
      for /F "tokens=1,2 delims=," %%A in ("!argv!") do (%\n%
         for /f "tokens=* delims=" %%# in ('%%~A') do endlocal^&set "%%~B=%%#" %\n%
      ) %\n%
   ) %\n%
) ^& set argv=,

::::: -------- ::::::::


:::EXAMPLE
%assign% "WHOAMI /LOGONID",result
echo %result%
::::::::::::::::::::::::::::::::::::::::::::::::::
;;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%
@echo off

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

chcp %[[%code-page%]]%
echo ~~%code-page%~~

whoami %[[%its-me%]]%
echo ##%its-me%##