Batch file 使用MS批处理文件将程序的输出分配给变量
我需要使用MS批处理文件将程序的输出分配给变量 因此,在GNUBash shell中,我将使用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
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%##