Puoi usare un here-doc e. procuratelo per un modello di collettore generale efficiente e compatibile con POSIX.
. 8<<-\IOHERE /proc/self/fd/8
command
…
fn() { declaration ; } <<WHATEVER
# though a nested heredoc might be finicky
# about stdin depending on shell
WHATEVER
cat -u ./stdout | ./works.as >> expect.ed
IOHERE
Quando apri l'ereditarietà, segnali alla shell con un token di input IOHERE che dovrebbe reindirizzare il suo input al descrittore di file specificato fino a quando non incontra l'altra estremità del token limiter. Mi sono guardato intorno ma non ho visto molti esempi dell'uso del numero fd di reindirizzamento, come ho mostrato sopra in combinazione con l'operatore heredoc, sebbene il suo utilizzo sia chiaramente specificato nelle linee guida di comando shell POSIX di base. La maggior parte delle persone punta semplicemente su stdin e spara, ma trovo che gli scriptlet di sourcing in questo modo possano mantenere lo stdin libero e le app costituenti da lamentarsi dei percorsi I / o bloccati.
Il contenuto dell'eredoc viene trasmesso in streaming al descrittore di file specificato, che a sua volta viene quindi interpretato come codice shell ed eseguito da. incorporato, ma non senza specificare un percorso specifico per. . Se il percorso / proc / self ti dà problemi, prova / dev / fd / n o / proc / $$. Questo stesso metodo funziona sui tubi, a proposito:
cat ./*.sh | . /dev/stdin
È probabilmente meno saggio di quanto sembri. Puoi fare lo stesso con sh, ovviamente, ma lo scopo di. È quello di eseguire nell'attuale ambiente shell, che è probabilmente quello che vuoi e, a seconda della tua shell, è molto più probabile che lavori con un heredoc che con una pipe anonima standard.
Comunque, come probabilmente avrai notato, non ho ancora risposto alla tua domanda. Ma se ci pensi, allo stesso modo in cui l'ereditarietà trasmette tutto il tuo codice a.
. 5<<EOIN /dev/fd/5 |\
tee -a ./log.file | cat -u >$(tty)
script
…
more script
EOIN
Quindi tutto il terminale stdout da qualsiasi codice eseguito nella tua eredità viene reindirizzato. ovviamente e può essere facilmente staccato da una singola pipa. Ho incluso la chiamata cat senza buffer perché non sono chiaro sull'attuale direzione stdout, ma è probabilmente ridondante (quasi sicuramente è come scritto comunque) e la pipeline può probabilmente terminare proprio a T.
Potresti anche mettere in dubbio la citazione di barra rovesciata mancante nel secondo esempio. Questa parte è importante da capire prima di saltare e potrebbe darti alcune idee su come può essere utilizzata. Un limitatore ereditario citato (finora abbiamo usato IOHERE ed EOIN, e il primo che ho citato con una barra rovesciata, sebbene le virgolette "singole" o "doppie" avrebbero lo stesso scopo) impediranno alla shell di eseguire qualsiasi espansione di parametro sul contenuti, ma un limitatore non quotato lascerà i suoi contenuti aperti all'espansione. Le conseguenze di ciò quando la tua eredità è. provenienti sono drammatici:
. 3<<HD ${fdpath}/3
: \${vars=$(printf '${var%s=$((%s*2))},' `seq 1 100`)}
HD
echo $vars
> 4,8,12…
echo $var1 $var51
> 4 104
Poiché non ho citato il limitatore ereditario, la shell ha espanso il contenuto mentre lo leggeva e prima di servire il descrittore di file risultante. eseguire. Ciò essenzialmente ha comportato l'analisi dei comandi due volte, comunque quelli espandibili. Poiché la barra rovesciata ha citato l'espansione del parametro $ vars, la shell ha ignorato la sua dichiarazione al primo passaggio e ha rimosso la barra rovesciata in modo che l'intero contenuto espanso della stampa potesse essere valutato da null quando. proveniente dallo script al secondo passaggio.
Questa funzionalità è fondamentalmente esattamente ciò che la pericolosa shell eval incorporata può fornire, anche se la citazione è molto più facile da gestire in una eredità che con eval, e può essere altrettanto pericolosa. A meno che non lo pianifichi attentamente, probabilmente è meglio citare il limitatore "EOF" come una questione di abitudine. Sto solo dicendo.
EDIT: Eh, sto guardando indietro a questo e pensando che sia un po 'troppo lungo. Se TUTTO ciò che devi fare è concatenare più output in una pipe, il metodo più semplice è usare solo un:
{ or ( command ) list ; } | tee -a ea.sy >>pea.sy
I ricci cercheranno di eseguire i contenuti nella shell corrente mentre i genitori verranno automaticamente sottoposti a sub-out. Tuttavia, chiunque può dirtelo e, almeno secondo me, il. La soluzione ereditaria è un'informazione molto più preziosa, specialmente se vuoi capire come funziona realmente la shell.
Divertiti!