2013-02-19 159 views
39

您可以使用管道将命令的输出重定向到变量吗?将命令的输出设置为变量(带管道)

我还没有试过像我一直没能想到的任何尝试,但我已经试过一个方法(有两个变化)...

例如:

echo Hello|set text= 

没有工作,也没有:

echo Hello | set text= 

我知道你可以用FOR命令做到这一点很容易,但我认为它看起来“漂亮”与管道。

如果你想知道,我没有一个具体的原因,我问这个,而不是我很好奇,我找不到答案。

+1

检查多尔的答案在这里:http://stackoverflow.com/questions/6359820/batch-files-how-to-set-命令 - 输出为变量 - 如果你真的不想使用你可以使用临时文件。虽然没有办法用管道来做。 – Vicky 2013-02-19 10:35:43

+1

此问题在此处详细描述:http:// stackoverflow。com/questions/8192318 /为什么 - 延迟扩展 - 失败时 - 管道内部的代码块 – Aacini 2013-02-19 12:48:33

+0

http://superuser.com/a/1007898/429721已针对管道完善,stdout/err重定向,多个可执行文件,输出存储和处理值作为数字和其他操作...工作得很好.. – 2015-12-02 00:37:36

回答

38

你的方式不能工作有两个原因。

您需要使用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% 
+3

因此,没有临时文件或“for”命令的限制是没有办法的?即使没有,谢谢。 – 2013-02-20 05:38:16

+0

显然你可以使用'FOR',但是你不需要管道。这同样适用于临时文件 – jeb 2013-02-20 05:45:01

+1

顺便说一句,它出现在我的测试中,你只能在for语句中使用1个命令。您无法将更多命令与&一起链接。 – 2013-10-04 18:52:31

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% 
+1

很有技巧。尽管避免临时文件通常很好。 – zanlok 2015-11-13 16:45:28

11

缺乏一个类似Linux的backtick/backquote设施是预PowerShell的世界的一大烦恼。通过for-loops使用反引号并不舒适。所以我们需要一些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" 
+0

'usebackq delims ='部分在那里做了什么? – 2015-05-10 12:31:21

+1

@RichardLeMesurier:'usebackq'指定使用类似linux的语义,其中反引号字符串作为命令执行,输出解析为'for'变量(此处为'%% a')。 'delims = x'指定分析中使用的分隔符(这里没有分隔符)。 – antonio 2015-05-11 22:17:33

+0

Thx澄清。我使用这种模式在构建工具中取得了巨大的成功。这个答案应该是可以接受的。 – 2015-05-12 06:42:17

3

这不使用管道,但需要一个临时文件
我用这把简单的时间戳为lowtech日常维护batfile

我们已经短期将我们的系统时间格式化为HHmm(这对于10:45 PM是2245)
我使用$ DATE%@%TIME%时间戳将Maint-Routines的输出直接输出到日志文件;
。 。 。但%TIME%是长难看字符串(如224513.56,对于降低到秒的百分之。)

解决方案概述:
1.使用重定向(“>”),以发送命令“TIME/T”每次要覆盖一个临时文件在%temp%目录
2.然后使用该临时文件作为输入来设置一个新的变量(I称之为NOW)
3.更换

echo $DATE%@%TIME% blah-blah-blah >> %logfile%
     与
echo $DATE%@%NOW% blah-blah-blah >> %logfile%


====输出差异:
BEFORE:
SUCCESSFUL TIMESYNCH [email protected]
AFTER:
SUCCESSFUL TIMESYNCH [email protected]


实际代码:

TIME /T > %TEMP%\DailyTemp.txt 
SET /p NOW=<%TEMP%\DailyTemp.txt 
echo $DATE%@%NOW% blah-blah-blah >> %logfile%


后果:
剩下事后所附日志文件,并不断改写临时文件。如果临时文件被删除,它将根据需要重新创建。

+0

这实际上是我尝试传递复杂git命令时工作的唯一解决方案,例如'git log --pretty = format:%ad_commit_%h -n 1 --date = short'。 – 2017-04-05 16:16:43

+0

简单而有效 – 2017-08-05 00:10:37

-1

您可以将输出设置为临时文件,然后从文件中读取数据,然后可以删除临时文件。

echo %date%>temp.txt 
set /p myVarDate= < temp.txt 
echo Date is %myVarDate% 
del temp.txt 

在此变量 “myVarDate” 包含命令的输出

+3

已经有3个旧的答案提到临时文件。我看不到你的答案的进一步好处? – jeb 2017-04-12 13:32:19