Tome stdin del archivo pero aún así aparece en la terminal

9

Tengo un programa que requiere que ingrese datos a medida que se ejecuta el programa. Imagínese algo así:

$ ./program
Hi there. What's your name? Zambezi
What is your quest? To make a program which runs nicely
What is your favourite color? Red
...

Ahora, tengo varias entradas de prueba para ejecutar mi programa. Todos contienen algo como:

Arthur, King of the Britons
To seek the Holy Grail
...

Sin embargo, algunos de mis scripts de prueba fallan, y desafortunadamente es muy difícil para mí descifrar exactamente dónde fallaron, ya que mi terminal se ve así:

$ ./program < arthur.txt
Hi there. What's your name?What is your quest?What is your favourite color?...

¿Hay alguna manera de que todavía pueda dar entrada a stdintravés de un archivo, pero aún así el terminal aparece como si lo hubiera escrito todo?

Linux Mint 16 es mi sistema operativo si eso importa.

Zambeze
fuente
No sé cómo hacer esto, pero "debería" poder hacerlo usando dispositivos tty (sin búfer). Consulte stackoverflow.com/questions/8514735/… para obtener algunas pistas.
Joe

Respuestas:

13

En lugar de utilizar la redirección de entrada (./program <arthur.txt), que es solo almacenar la entrada en su programa, debe usar herramientas como "esperar" para esperar la pregunta y enviar las respuestas una por una.

#!/usr/bin/expect
log_user 0
spawn ./program
log_user 1

expect {
  "*?"
}
send "Arthur, King of the Britons\r"

expect {
  "*?"
}
send "To seek the Holy Grail\r"

expect {
  "*?"
}
send "...\r"

Mejores ejemplos: http://www.pantz.org/software/expect/expect_examples_and_tips.html

algun usuario
fuente
Una vez que haya hecho funcionar lo anterior, puede convertirlo en un expectscript que sepa qué provoca los problemas de su programa y sabe alimentar su programa con la tercera línea de entrada en respuesta al "¿Cuál es su color favorito?" pregunta - y luego haga que el expectscript lea el arthur.txtarchivo (o cualquier otro archivo especificado, adecuadamente estructurado) para obtener esas entradas, en lugar de tenerlas codificadas en el script.
G-Man dice 'Reincorporar a Monica' el
7

Esto es exactamente para lo que teese usa.

Por ejemplo:

$  echo foo | tee >( grep bar ) 
foo
$

Lo que sucede aquí es que tee toma stdin y lo copia en stdout y lo canaliza nuevamente. Al igual que en la junta para tuberías.

Consulte la camiseta de la página de manual (1) para obtener más detalles.

Dwight Spencer
fuente
1
Sin embargo, ¿se garantiza que los mensajes aparecerán en el orden correcto? Incluso ignorando el almacenamiento en búfer, se trata esencialmente de dos programas que se ejecutan simultáneamente e intentan escribir en la misma pantalla.
Federico Poloni
1
Sin embargo, ¿cómo se usa esto en mi escenario? Intenté leer las páginas de manual, pero parece que hay mucho más en esta herramienta que solo mi caso de uso, y no estaba entendiendo cómo lo usaría cuando se trata de program.exey arthur.txt.
Zambezi
@Zambezicat arthur.txt | tee >( program.exe )
gronostaj
2
Esto fue lo primero que me vino a la mente también. Pero lo he intentado y confirmado que no funciona. La salida se muestra por separado. En mi experimento, el contenido de arthur.txt aparece primero, seguido de las preguntas de program.exe. Es posible que pueda hacer que funcione con "unbuffer" de esperar, pero no he tenido suerte.
algún usuario