您可以将命令的输出重定向到带有管道的变量吗?
我没有尝试太多,因为我想不出任何可以尝试的方法,但我尝试了一种方法(有两种变体)......
例如:
echo Hello|set text=
没有工作,也没有:
echo Hello | set text=
我知道你可以用这个命令很容易地做到这一点FOR
,但我认为用管道看起来会“更好”。
如果你想知道,除了我很好奇而且我找不到答案之外,我没有具体的理由问这个问题。
您可以将命令的输出重定向到带有管道的变量吗?
我没有尝试太多,因为我想不出任何可以尝试的方法,但我尝试了一种方法(有两种变体)......
例如:
echo Hello|set text=
没有工作,也没有:
echo Hello | set text=
我知道你可以用这个命令很容易地做到这一点FOR
,但我认为用管道看起来会“更好”。
如果你想知道,除了我很好奇而且我找不到答案之外,我没有具体的理由问这个问题。
你的方法行不通有两个原因。
您需要使用用户输入set /p text=
来设置变量。
另一个问题是管道。
管道启动两个异步 cmd.exe 实例,完成作业后两个实例都关闭。
这就是为什么似乎没有设置变量的原因,但是一个小例子表明它们已设置但后来结果丢失了。
set myVar=origin
echo Hello | (set /p myVar= & set myVar)
set myVar
输出
Hello
origin
替代方案:您可以使用 FOR 循环将值放入变量或临时文件中。
for /f "delims=" %%A in ('echo hello') do set "var=%%A"
echo %var%
或者
>output.tmp echo Hello
>>output.tmp echo world
<output.tmp (
set /p line1=
set /p line2=
)
echo %line1%
echo %line2%
用宏替代:
您可以使用批处理宏,这有点像 bash 等价物
@echo off
REM *** Get version string
%$set% versionString="ver"
echo The version is %versionString[0]%
REM *** Get all drive letters
`%$set% driveLetters="wmic logicaldisk get name /value | findstr "Name""
call :ShowVariable driveLetters
宏的定义可以在
SO:Assign output of a program to a variable using a MS batch file 中找到
缺乏类似 Linux 的反引号/反引号工具是前 PowerShell 世界的主要烦恼。通过 for 循环使用反引号一点也不方便。所以我们需要某种setvar myvar cmd-line
命令。
在我%path%
的目录中,我有一个包含许多垃圾箱和批次的目录来应对那些 Win 缺点。
我写的一批是:
:: setvar varname cmd
:: Set VARNAME to the output of CMD
:: Triple escape pipes, eg:
:: setvar x dir c:\ ^^^| sort
:: -----------------------------
@echo off
SETLOCAL
:: Get command from argument
for /F "tokens=1,*" %%a in ("%*") do set cmd=%%b
:: Get output and set var
for /F "usebackq delims=" %%a in (`%cmd%`) do (
ENDLOCAL
set %1=%%a
)
:: Show results
SETLOCAL EnableDelayedExpansion
echo %1=!%1!
所以在你的情况下,你会输入:
> setvar text echo Hello
text=Hello
该脚本会通知您结果,这意味着您可以:
> echo text var is now %text%
text var is now Hello
您可以使用任何命令:
> setvar text FIND "Jones" names.txt
如果您想通过管道传输到某个变量的命令本身包含一个管道怎么办?
三重逃脱它,^^^|
:
> setvar text dir c:\ ^^^| find "Win"
这不使用管道,但需要一个临时文件
我用它来将简化的时间戳放入低技术日常维护 batfile
我们已经将我们的系统时间短格式设置为 HHmm,(晚上 10:45 为 2245)
我直接输出维护例程到具有 $DATE%@%TIME% 时间戳的日志文件;
. . . 但 %TIME% 是一个长而丑陋的字符串(例如 224513.56,低至百分之一秒)
解决方案概述:
1. 每次使用重定向 (">") 发送命令“TIME /T”以覆盖 %TEMP% DIRECTORY 中的临时文件
2. 然后使用该临时文件作为输入来设置新变量(我现在叫它)
3. 替换
回声 $DATE%@%TIME% 等等等等 >> %logfile%和
回声 $DATE%@%NOW% 等等等等 >> %logfile%
成功的时间同步 29Dec14@222552.30后:
成功的时间同步 29Dec14@2252
实际代码:
时间 /T > %TEMP%\DailyTemp.txt SET /p NOW=<%TEMP%\DailyTemp.txt 回声 $DATE%@%NOW% 等等等等 >> %logfile%
之后:
之后剩下的就是附加的日志文件,并且不断覆盖临时文件。如果临时文件被删除,它将根据需要重新创建。
我发现自己对在互联网上任何地方都缺乏我认为这个问题的最佳答案感到有点惊讶。我挣扎了很多年才找到答案。网上很多答案都很接近,但没有一个真正回答。真正的答案是
(cmd & echo.) >2 & (set /p =)<2
“秘密调味料”是“回声”的“严密保护的令人垂涎的秘密”。发送 CR/LF (ENTER/new line/0x0D0A)。否则,我在这里所做的是将第一个命令的输出重定向到标准错误流。然后我将标准错误流重定向到“set /p =”命令的标准输入流。
例子:
(echo foo & echo.) >2 & (set /p bar=)<2
在批处理文件中,我通常在临时目录中创建一个文件并附加程序的输出,然后我用变量名调用它来设置该变量。像这样:
:: Create a set_var.cmd file containing: set %1=
set /p="set %%1="<nul>"%temp%\set_var.cmd"
:: Append output from a command
ipconfig | find "IPv4" >> "%temp%\set_var.cmd"
call "%temp%\set_var.cmd" IPAddress
echo %IPAddress%
您可以将输出设置为临时文件,然后从文件中读取数据,然后您可以删除临时文件。
echo %date%>temp.txt
set /p myVarDate= < temp.txt
echo Date is %myVarDate%
del temp.txt
在这个变量myVarDate
中包含命令的输出。