Answers:
一种方法是:
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%
for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
作为此先前答案的补充,可以在for语句内使用管道,并使用脱字符号进行转义:
for /f "tokens=*" %%i in ('tasklist ^| grep "explorer"') do set VAR=%%i
for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %i
但是,通常,usebackq
应使用来处理复杂的命令。
for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i
。如果命令本身没有引号,对我来说更容易。
假设您的应用程序的输出是数字返回码,则可以执行以下操作
application arg0 arg1
set VAR=%errorlevel%
执行中:for /f %%i in ('application arg0 arg1') do set VAR=%%i
我遇到错误:%% i此时是意外的。作为解决方法,我必须执行以上操作for /f %i in ('application arg0 arg1') do set VAR=%i
%%
的批处理文件中,以及在命令行上需要的批处理文件之外%
除了答案之外,您不能在循环的设置部分中直接使用输出重定向运算符for
(例如,如果您想隐藏用户的stderror输出并提供更好的错误消息)。相反,您必须使用脱字符号(^
)对其进行转义:
for /f %%O in ('some-erroring-command 2^> nul') do (echo %%O)
@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
您可以使用批处理宏来简单地捕获命令输出,就像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
我编写了每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