2013-02-19 160 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