2015-05-05 81 views
1

我想將特定編號的文件描述符流到Bash中的變量中。我可以使用下面的函數從正常的標準中做到這一點,但是,它是如何從特定的文件描述符中完成的。如果我使用相同的方法,我需要將FD引入子shell。我總是可以一行一行閱讀,但如果我能夠連續閱讀,那麼這將是非常可取的。流特定編號的Bash文件描述符到變量中

我所擁有的功能是:

streamStdInTo() 
{ 
    local STORE_INvar="${1}" ; shift 
    printf -v "${STORE_INvar}" '%s' "$(cat -)" 
} 

是的,我知道這不會是一個管道末端正常工作都將丟失(因爲它在一個子shell執行),但是,或者在與啓動相同的shell中執行管道結束的方法Bash 4 set +m ; shopt -s lastpipe,或者通過不同的文件描述符指向這個方法,我希望能夠使用它。

所以,我的問題是,我如何使用上述但與正常不同的文件描述符?

回答

2

這不是完全清楚你的意思,但也許你正在尋找的東西,如:

cat - <&4 # read from fd 4 

或者,只是叫你目前的功能與重定向:

streamStdInTo foo <&4 

編輯: 尋址從評論的一些問題,你可以使用一個fifo:

#!/bin/bash 

trap 'rm -f $f' 0 
f=$(mktemp xxx) 
rm $f 
mkfifo $f 
echo foo > $f & 
exec 4< $f 
cat - <&4 
wait 
+0

嘿,那裏,謝謝你的回答,我在這裏遇到的問題似乎是雞和雞蛋/ bootstrap場景。即,如果文件描述符已經打開並且被映射到流,那麼按照你所說的那樣執行FD4的命令的方向是好的。儘管我想做的事情是將流水線的末端流式傳輸到變量中,但使用文件描述符來避免子外殼問題,但是,似乎我無法通過映射到未知問題來初始化問題的任何一端,分配的文件描述符。所以,說我映射fd 4到一個文件,那麼它會一切正常,我可以流入和流出罰款... – user4838443

+0

我的問題是直接去,如何使用兩個事情之間映射一個未使用的文件描述符?如果我需要在一端打開它,然後才能在另一端打開,那麼我該怎麼做?我真的很感激任何人的想法! – user4838443

+0

假設我有一個流水線,如下所示:'$ printf'\ n \ n123 \ n456 \ n524 \ n789 \ n \ n \ n'| grep 2',我想通過文件描述符將值傳遞給當前shell中的變量,以避免子shell問題。考慮到試圖在流水線結束時或者在等式的變量賦值一端分配給未使用的FD,我怎麼做這些,不要讓我使用先前未分配的文件描述符來做到這一點。 – user4838443

0

我認爲對於你想要做什麼感到困惑。如果我理解正確,那麼這裏的最終目標是運行管道並將輸出捕獲到變量中,對嗎?有點像這樣:

var=$(cmd1 | cmd2) 

除了我猜的想法在這裏是「$ VAR」的名字存儲在另一個變量:

varname=var 

你可以做一個繞擊通常的最終運行通過使用流程替代來控制工作情況。因此,而不是這種正常的管道(這將在KSH或zsh的工作,而不是在bash,除非你設置lastpipe):

cmd1 | cmd2 | read "$varname" 

你可以使用這個命令,這是從殼如何處理工作分開相當於:

read "$varname" < <(cmd1 | cmd2) 

通過進程替換,「read $ varname」不在管道中運行,因此Bash不會運行它。 (你可以使用你的streamStdInTo()函數有作爲,當然)

據我瞭解,你想通過使用數字文件描述符來解決這個問題:

cmd1 | cmd2 >&$fd1 & 
read "$varname" <&$fd2 

創建這些文件描述符將管道後臺作業連接到「讀取」命令,您需要將其稱爲管道或FIFO。這些可以被創建而不需要接觸文件系統(shell一直在做!)但是shell並沒有直接公開這個功能,這就是爲什麼我們需要使用mkfifo來創建一個命名管道。命名管道是存在於文件系統上的一個特殊文件,但是您寫入的數據不會存入磁盤。這是存儲在內存中的數據隊列(管道)。它並不需要留在文件系統中你打開後,無論是,它幾乎可以立即刪除:

pipedir=$(mktemp -d /tmp/pipe_maker_XXXX) 
mkfifo ${pipedir}/pipe 
exec {temp_fd}<>${pipedir}/pipe   # Open both ends of the pipe 
exec {fd1}>${pipedir}/pipe 
exec {fd2}<${pipedir}/pipe 
exec {temp_fd}<&-      # Close the read/write FD 
rm -rf ${pipedir}      # Don't need the named FIFO any more 

一個在外殼使用命名管道工作的困難是,試圖打開他們只是爲了閱讀,或者僅僅爲了寫作而導致呼叫阻塞,直到打開管道的另一端。在嘗試打開另一端之前,可以通過在後臺作業中打開一端來解決該問題,或者像上述那樣一次打開兩端。

「{fd} < ...」語法將未使用的文件描述符編號動態分配給變量$ fd,並在該文件描述符上打開該文件。它的年齡(自1993年以來)一直在ksh左右,但在Bash中,我認爲它只能回到4.1(從2010年)。