是否可以将批处理文件中语句的输出设置为变量,例如:
findstr testing > %VARIABLE%
echo %VARIABLE%
是否可以将批处理文件中语句的输出设置为变量,例如:
findstr testing > %VARIABLE%
echo %VARIABLE%
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var=%%F
)
ECHO %var%
我总是使用USEBACKQ,这样如果你有要插入的字符串或者一个很长的文件名,你就可以在不弄乱命令的情况下使用双引号。
现在如果你的输出会包含多行,你可以这样做:
SETLOCAL ENABLEDELAYEDEXPANSION
SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`command`) DO (
SET var!count!=%%F
SET /a count=!count!+1
)
ECHO %var1%
ECHO %var2%
ECHO %var3%
ENDLOCAL
ENABLEDELAYEDEXPANSION
时,它们将被解释为控制字符。 - JonathanDavidArndtcommand
的退出代码?我确定它返回了一个非零代码,但是无论我在哪里尝试使用%ERRORLEVEL%
(甚至在do
块内部),它始终包含0。所以我猜测for
结构的某个部分正在覆盖它。顺便说一句,为了做这么基本的事情需要写出如此疯狂的代码,真是难以置信。 - David Ferenczy RogožanSET var!count!=%%F
在批处理文件中,我以前从未见过动态变量名称。 - GregHNZ一句话概括:
FOR /F "tokens=*" %%g IN ('your command') do (SET VAR=%%g)
命令输出将先设置为 %g,然后再设置为 VAR。
更多信息在这里:https://ss64.com/nt/for_cmd.html
我在那个叫做Interweb的地方找到了这个帖子。总结如下:
@echo off
setlocal enableextensions
for /f "tokens=*" %%a in (
'VER'
) do (
set myvar=%%a
)
echo/%%myvar%%=%myvar%
pause
endlocal
您也可以将命令输出重定向到临时文件,然后将该临时文件的内容放入您的变量中,如下所示。但是,它无法处理多行输入。
cmd > tmpFile
set /p myvar= < tmpFile
del tmpFile
感谢Tom's Hardware论坛上的帖子。
FOR /F %i IN ('findstr testing') DO set VARIABLE=%i
echo %VARIABLE%
如果您想用双引号括起搜索字符串:
FOR /F %i IN ('findstr "testing"') DO set VARIABLE=%i
如果你想把这段代码存储在批处理文件中,需要添加一个额外的%符号:
FOR /F %%i IN ('findstr "testing"') DO set VARIABLE=%%i
FOR /F %i IN ('dir /b /a-d "%cd%" ^| find /v /c "?"') DO set /a count=%i
请注意,在命令括号中使用单引号而不是双引号"或重音符号`。这是在for循环中比delims、tokens或usebackq更清洁的替代方法。
更新于2021年8月27日:
另一种方法是设置errorlevel变量,尽管许多人会劝阻在大型脚本或刚接触已安装操作系统变体的cmd风格时设置errorlevel。
此方法适用于要存储的(返回)值适合32位整数的情况。
例如:计算目录中文件数量并将其存储在名为count
的变量中:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& cmd /c exit /b %myVar%)
set count=%errorlevel%
详细 - Win CMD 整数限制测试:
Win CMD 算术限制:2147483647(32 位整数)
堆栈溢出将在 -2147483648 继续计数, 并在达到 2147483647 后重新设置
REM See tests below:
cmd /c exit /b 2147483647
echo %errorlevel%
2147483647
cmd /c exit /b 2147483648
echo %errorlevel%
-2147483648
cmd /c exit /b 2147483649
echo %errorlevel%
-2147483647
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& set myVar)
读取文件的方法是...
set /P Variable=<File.txt
写入文件
@echo %DataToWrite%>File.txt
注意:在 <> 字符之前添加空格会导致变量末尾添加一个空格
要将内容添加到文件中(例如日志程序),首先创建一个名为 e.txt 的文件,里面只包含一个回车键。
set /P Data=<log0.log
set /P Ekey=<e.txt
@echo %Data%%Ekey%%NewData%>log0.txt
你的日志将会是这样的
Entry1
Entry2
等等之类的
无论如何,有几个有用的东西
所有这些答案都非常接近我所需要的答案。这是对它们的进一步扩展。
如果你正在运行一个.bat
文件,并且你想要一个单行命令来将类似jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json
这样复杂的命令导出到一个名为AWS_ACCESS_KEY
的变量中,那么你需要这个:
FOR /F "tokens=* USEBACKQ" %%g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%%g")
如果您处于C:\
提示符下,您需要一条单行命令来运行像jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json
这样复杂的命令,并将其赋值给名为AWS_ACCESS_KEY
的变量,则需要使用以下命令:
FOR /F "tokens=* USEBACKQ" %g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET "AWS_ACCESS_KEY=%g")
以上两个答案的唯一区别在于在命令行中,您使用单个%来表示变量。 在批处理文件中,您必须加倍百分号(%%)。
由于命令包括冒号,引号和括号,因此需要在选项中包含USEBACKQ
行,以便您可以使用反引号指定要运行的命令,然后在其中使用各种有趣的字符。
一些笔记和一些技巧。
将结果分配给变量的“官方”方式是使用 FOR /F
,尽管在其他答案中也展示了如何使用临时文件。
对于命令处理,FOR
命令有两种形式,取决于是否使用 usebackq
选项。在下面的所有示例中,整个输出都被使用,而不会将其拆分。
FOR /f "tokens=* delims=" %%A in ('whoami') do @set "I-Am=%%A"
FOR /f "usebackq tokens=* delims=" %%A in (`whoami`) do @set "I-Am=%%A"
如果直接在控制台中使用:
FOR /f "tokens=* delims=" %A in ('whoami') do set "I-Am=%A"
FOR /f "usebackq tokens=* delims=" %A in (`whoami`) do set "I-Am=%A"
%%A
是一个临时变量,仅在FOR
命令上下文中可用,称为token。这两种形式在处理包含特定引号的参数时非常有用。它在其他语言或WMIC的REPL界面中特别有用。尽管在这两种情况下,表达式都可以用双引号括起来进行处理。
这里有一个使用Python的例子(可以将方括号中的表达式转移到单独的一行中,以便更容易阅读):
@echo off
for /f "tokens=* delims=" %%a in (
'"python -c ""print("""Message from python""")"""'
) do (
echo processed message from python: "%%a"
)
为在同一FOR块中使用分配的变量,还需检查DELAYED EXPANSION
为了避免编写FOR命令的所有参数,您可以使用MACRO将结果分配给变量:
@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%
宏的第一个参数是命令,第二个参数是我们想使用的变量名称,两个参数之间用,
(逗号)分隔。尽管这只适用于简单直接的情况。
如果我们想为控制台创建类似的宏,可以使用DOSKEY。
doskey assign=for /f "tokens=1,2 delims=," %a in ("$*") do @for /f "tokens=* delims=" %# in ('"%a"') do @set "%b=%#"
rem -- example --
assign WHOAMI /LOGONID,my-id
echo %my-id%
DOSKEY接受双引号作为参数的包含符号,因此对于更简单的情况也很有用。
FOR也可以与管道一起使用,用于链接命令(虽然不适用于变量赋值)。
hostname |for /f "tokens=* delims=" %%# in ('more') do @(ping %%#)
可以通过宏来美化它:
@echo off
:: --- defining chain command macros ---
set "result-as-[arg]:=|for /f "tokens=* delims=" %%# in ('more') do @("
set "[arg]= %%#)"
::: -------------------------- :::
::Example:
hostname %result-as-[arg]:% ping %[arg]%
为了完整起见,这里提供基于临时文件方法的宏(没有doskey定义,但也很容易实现。如果你使用的是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%##
使用 /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%
dir /w "\\.\pipe\\"|find "pageant" > %temp%\SSH_PAGEANT_AUTH_SOCK && set /P SSH_PAGEANT_AUTH_SOCK=<%temp%\SSH_PAGEANT_AUTH_SOCK
cd %windir%\system32\inetsrv
@echo off
for /F "tokens=* USEBACKQ" %%x in (
`appcmd list apppool /text:name`
) do (
echo|set /p= "%%x - " /text:name & appcmd.exe list apppool "%%x" /text:processModel.identityType
)
echo %date% & echo %time%
pause
appcmd
不是标准程序,我也看不到你在哪里将程序输出分配给变量。最后,你需要更多的解释。 - jeb