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

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

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

类似set VAR=application arg0 arg1

类似的问题

389855 次浏览

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

application arg0 arg1
set VAR=%errorlevel%

@OP,你可以使用for循环来捕获程序的返回状态,如果它输出的不是数字的话

一种方法是:

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

另一个原因是:

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

注意,%%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循环的部分直接使用输出重定向操作符(例如,如果你想对用户隐藏错误输出并提供更好的错误消息)。相反,你必须用一个插入字符(^)来转义它们:

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

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

@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

在命令行中执行以下命令时:

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

我得到了错误:

%%i was unexpected at this time.

为了解决这个问题,我改为使用一个%符号,如下所示:

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

总结:

  • 在批处理文件中使用%%
  • 在批处理文件之外使用%(在命令行上)

我写了脚本,每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

您可以使用批处理宏来简单地捕获命令输出,这有点像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

一些宏用于将命令的输出设置为变量/

在命令提示符中直接为

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%

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

//设置str = % myvar#: *: = %// this replace all before "“;“ ;                                                         //子网掩码;my_log.txt祝辞my_find.txt//搜索“;字符串”;在文件中并保存在新文件中 //““”;如果使用">>"添加旧文件//我推荐使用">"

@echo off
 

ipconfig > my_log.txt
findstr "Subnet Mask" my_log.txt > my_find.txt
set /p myVar= < my_find.txt
echo %myVar%


set str=%myVar:*:=%
set str=%str:.= im_dot %
echo %str%


pause

这个答案可能也有帮助:https://stackoverflow.com/a/61666083/2444948

但是它实际上是在写一个文件来读取它… 代码不是来自我:

(cmd & echo.) >2 & (set /p =)<2


REM Example :
(echo foo & echo.) >2 & (set /p bar=)<2