Pegue o stdin do arquivo, mas ele ainda aparece no terminal

9

Eu tenho um programa que exige que eu insira dados enquanto o programa é executado. Imagine algo assim:

$ ./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
...

Agora, tenho várias entradas de teste para executar meu programa. Todos eles contêm algo como:

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

No entanto, alguns dos meus scripts de teste falham e, infelizmente, é muito difícil para mim decifrar exatamente onde eles falharam, pois meu terminal se parece com isso:

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

Existe uma maneira que eu ainda possa dar entrada stdinatravés de um arquivo, mas ainda assim o terminal apareça como se eu tivesse digitado tudo?

Linux Mint 16 é o meu sistema operacional, se isso importa.

Zambeze
fonte
Não sei como fazer isso, mas você "deveria" conseguir fazer isso usando dispositivos tty (sem buffer). Consulte stackoverflow.com/questions/8514735/… para obter algumas dicas.
Joe

Respostas:

13

Em vez de usar o redirecionamento de entrada (./program <arthur.txt), que está apenas armazenando um buffer no seu programa, você deve usar ferramentas como "esperar" para aguardar a pergunta e enviar as respostas uma a uma.

#!/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"

Melhores exemplos: http://www.pantz.org/software/expect/expect_examples_and_tips.html

algum usuário
fonte
Depois de fazer o trabalho acima, você poderá transformá-lo em um expectscript que saiba o que causa problemas no seu programa e saiba que ele alimenta a terceira linha de entrada em resposta ao "Qual é a sua cor favorita?" pergunta - e faça com que o expectscript leia o arthur.txtarquivo (ou qualquer outro arquivo especificado, adequadamente estruturado) para obter essas entradas, em vez de tê-las codificadas no script.
G-Man diz 'Reinstate Monica'
7

É exatamente para isso que teeé usado.

Por exemplo:

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

O que acontece aqui é que o tee pega o stdin e o copia para o stdout e o envia novamente. Assim como na junta para tubos.

Verifique o tee da página de manual (1) para obter mais detalhes.

Dwight Spencer
fonte
11
As mensagens são garantidas para aparecer na ordem correta, no entanto? Mesmo ignorando o buffer, são essencialmente dois programas sendo executados simultaneamente e tentando gravar na mesma tela.
Federico Poloni
11
Como alguém usa isso no meu cenário? Tentei ler as páginas de manual, mas parece haver muito mais nessa ferramenta do que apenas meu caso de uso, e eu não estava conseguindo entender como usá-la quando se trata program.exee arthur.txt.
Zambeze
@Zambezicat arthur.txt | tee >( program.exe )
gronostaj
2
tee foi a primeira coisa que me veio à cabeça também. Mas eu tentei e confirmei que não funciona. A saída aparece separadamente. No meu experimento, o conteúdo do arthur.txt aparece primeiro, seguido pelas perguntas do program.exe. Você pode conseguir que ele funcione com um "buffer" de expectativa, mas não tive sorte.
algum usuário