Estou executando o Ubuntu Linux. Suponha que exista um programa chamado myprogram
. Este programa solicita entrada do usuário; especificamente, o usuário deve digitar um número inteiro quando solicitado e pressionar Enter. Gostaria de automatizar esse processo usando um script bash. Em particular, eu gostaria de executar myprogram
, digamos, 100 vezes (usando um contador i
que vai de 1
até 100
). Em cada execução de myprogram
, gostaria de inserir o valor atual de i
quando solicitado.
(A propósito, myprogram
leva options/switches -options
, todos os quais serão constantes e, portanto, especificados no script bash.)
Um esqueleto incompleto deste script bash pode ser:
#!/bin/bash
for i in {1..100}
do
myprogram -options
done
Agora gostaria de modificar o código acima para que o valor atual de i
seja inserido quando solicitado pelo programa. Qual é a melhor maneira de fazer isso?
O site do software que estou usando sugereusando <<EOF
no final da myprogram -options
linha. Eu acho que isso diz ao bash para olhar no "fim do arquivo" a entrada a ser usada. Mas e se eu não quiser colocar a entrada nofimdo arquivo? E se eu quiser colocá-lo imediatamente após o <<
ou <
?
A razão é que as coisas ficarão mais complicadas. Por exemplo, posso introduzir um contador inteiro j
que muda de alguma forma não linear e não sequencial. Eu gostaria então de alimentar o valor atual de j
to myprogram
em cada iteração, mas o valor de j
pode mudar entre a chamada myprogram -options
e o final do arquivo EOF
.
Você tem alguma sugestão?
Responder1
Para quase todos os programas, ambos echo $i | myprogram -options
e myprogram -options <<<$i
devem funcionar, alimentando o programa $i
através de entradas padrão.
<foo
usará o conteúdo do arquivo denominado foo
stdin.
<<foo
usará o texto entre isso e uma linha que consiste apenas foo
como entrada padrão. Isto é umaqui documento(heredoc), como disse Gilles; EOF
na verdade não significa o fim do arquivo, é apenas um delineador heredoc comum (usamos "foo" neste exemplo).
<<<foo
usará a string "foo" como entrada padrão. Você também pode especificar uma variável $foo
e o shell usará seu conteúdo como stdin, como mostrei acima. Isso é chamado decorda hereditária, pois usa uma string curta em contraste com um bloco inteiro, como em um heredoc. Herestrings funcionam no bash, mas não no /bin/sh
.
Responder2
A sintaxe recomendada por este site é chamada deaqui documento. A entrada para o programa de arquivo começa imediatamente abaixo da linha que contém <<EOF
e não termina no final do script, mas por uma linha que contém exatamente o texto EOF
(tome cuidado para não ter espaços em branco extras). A propósito, você pode usar qualquer marcador final que não contenha nenhum caractere especial do shell: EOF
não é uma palavra-chave, é meramente tradicional.
#!/bin/bash
for i in {1..100}
do
myprogram -options <<EOF
$i
EOF
for j in {1..42}; do
myprogram2 <<EOF
$i
$j
EOF
done
done
Responder3
aqui, documentos mencionados por Kevin e Gilles acima, ou tubulação simples funcionarão em muitos casos.
Para situações mais complicadas, você pode querer olhar para Expect ou similar (por exemplo, o módulo Expect::Simple CPAN é uma implementação Perl muito fácil de usar). pessoalmente, prefiro o módulo perl (o próprio Expect é tcl), mas existem implementações para muitas linguagens de script comuns. É até possível escrever ummuitoimplementação primitiva da ideia em sh ou bash usando while e read.
A ideia geral do Expect e de ferramentas semelhantes é esperar por uma string ou padrão especificado na saída de um programa e, em seguida, alimentá-lo com a entrada desejada.
Um exemplo de uso comum é automatizar o login, "esperando" (ou seja, aguardando) a string "ogin:", enviando o nome de login, depois esperando a string "word:" e enviando a senha.
Uma opção final, se você tiver a fonte do myprogram, é apenas modificá-la para receber a entrada que deseja fornecer como uma opção de linha de comando. Isso pode ser um pouco mais trabalhoso no início, mas será muito menos agravante do que brincar com o Expect ou canalizar dados para um programa que não foi projetado para ser usado dessa maneira.
... e não se esqueça de enviar seu patch para myprogram back upstream :) Mesmo que eles não gostem da maneira como você o codificou, eles podem gostar da ideia o suficiente para adicionar o recurso eles mesmos. Os desenvolvedores upstream tendem a apreciar as pessoas que se levantam e contribuem, em vez de exigir ou reclamar.