Puede usar un documento aquí y. búscalo para un modelo de colector general eficiente y amigable 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
Cuando abre el heredoc, le indica al shell con un token de entrada IOHERE que debe redirigir su entrada al descriptor de archivo que especifique hasta que encuentre el otro extremo de su token limitador. He mirado a mi alrededor, pero no he visto muchos ejemplos del uso del número fd de redirección como he mostrado anteriormente en combinación con el operador heredoc, aunque su uso está claramente especificado en las pautas básicas de comandos de shell POSIX. La mayoría de las personas solo apuntan a stdin y disparan, pero creo que el suministro de scriptlets de esta manera puede mantener el stdin libre y las aplicaciones constituyentes se quejan de las rutas de E / S bloqueadas.
El contenido del heredoc se transmite al descriptor de archivo que especifique, que a su vez es interpretado como código shell y ejecutado por. incorporado, pero no sin especificar una ruta específica para. . Si la ruta / proc / self le da problemas, intente / dev / fd / no / proc / $$. Este mismo método funciona en tuberías, por cierto:
cat ./*.sh | . /dev/stdin
Probablemente sea al menos tan imprudente como parece. Puede hacer lo mismo con sh, por supuesto, pero el propósito de. Es ejecutar en el entorno de shell actual, que es probablemente lo que desea y, dependiendo de su shell, es mucho más probable que funcione con un heredoc que con un tubo anónimo estándar
De todos modos, como probablemente habrás notado, todavía no he respondido tu pregunta. Pero si lo piensa, de la misma manera que el heredoc transmite todo su código a .'s in, también le proporciona un punto único y simple:
. 5<<EOIN /dev/fd/5 |\
tee -a ./log.file | cat -u >$(tty)
script
…
more script
EOIN
Entonces, todo el terminal stdout de cualquiera de los códigos ejecutados en su heredoc se extrae de. por supuesto y se puede extraer fácilmente de una sola tubería. Incluí la llamada de gato sin búfer porque no estoy claro sobre la dirección estándar actual, pero probablemente sea redundante (casi seguro es como está escrito de todos modos) y la tubería probablemente pueda terminar justo en el tee.
También puede cuestionar la cita de barra invertida que falta en el segundo ejemplo. Es importante comprender esta parte antes de ingresar y puede darle algunas ideas sobre cómo se puede usar. Un limitador heredoc citado (hasta ahora hemos usado IOHERE y EOIN, y el primero citado con una barra diagonal inversa, aunque las comillas 'simples' o "dobles" servirían para el mismo propósito) impedirá que el shell realice cualquier expansión de parámetros en el contenido, pero un limitador sin comillas dejará su contenido abierto a la expansión. Las consecuencias de esto cuando su heredoc es. de origen son dramáticos:
. 3<<HD ${fdpath}/3
: \${vars=$(printf '${var%s=$((%s*2))},' `seq 1 100`)}
HD
echo $vars
> 4,8,12…
echo $var1 $var51
> 4 104
Como no cité el limitador heredoc, el shell expandió el contenido a medida que lo leía y antes de mostrar el descriptor de archivo resultante. ejecutar. Esto esencialmente resultó en que los comandos se analizaran dos veces, los expandibles de todos modos. Debido a que la barra invertida citó la expansión del parámetro $ vars, el shell ignoró su declaración en la primera pasada y solo eliminó la barra invertida para que todo el contenido expandido de printf pudiera ser evaluado por nulo cuando. obtuvo el guión en el segundo paso.
Básicamente, esta funcionalidad es exactamente lo que puede proporcionar el peligroso shell de evaluación incorporado, incluso si la cita es mucho más fácil de manejar en un heredoc que con eval, y puede ser igualmente peligroso. A menos que lo planifique con cuidado, probablemente sea mejor citar el limitador "EOF" como una costumbre. Solo digo.
EDITAR: Eh, estoy mirando hacia atrás y pensando que es un poco exagerado. Si TODO lo que necesita hacer es concatenar varias salidas en una tubería, entonces el método más simple es usar un:
{ or ( command ) list ; } | tee -a ea.sy >>pea.sy
Los curlies intentarán ejecutar el contenido en el shell actual, mientras que los parens se eliminarán automáticamente. Aún así, cualquiera puede decirte eso y, al menos en mi opinión, el. La solución heredoc es información mucho más valiosa, especialmente si desea comprender cómo funciona realmente el shell.
¡Que te diviertas!