Automatizando a entrada textual de um script bash sem usar EOF

10

Estou executando o Ubuntu Linux. Suponha que haja um programa chamado myprogram . Este programa solicita ao usuário para entrada; especificamente, o usuário deve digitar um inteiro quando solicitado e pressionar Enter . Eu gostaria de automatizar esse processo usando um script bash. Em particular, gostaria de executar myprogram , digamos, 100 vezes (usando um contador i que vai de 1 a 100 ). Em cada execução de myprogram , gostaria de inserir o valor atual de i quando solicitado.

(A propósito, myprogram recebe opções / comutadores -options , todos os quais serão constantes e, portanto, especificados dentro do 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 sugere usando <<EOF no final de a linha myprogram -options . Eu acho que isso diz ao bash para olhar o "final do arquivo" para a entrada a ser usada. Mas e se eu não quiser colocar a entrada no end do arquivo? E se eu quiser colocá-lo imediatamente após o << ou < ?

A razão é que as coisas ficarão mais complicadas. Por exemplo, eu posso introduzir um contador inteiro j que muda de alguma forma não linear e não sequencial. Gostaria, então, de alimentar o valor atual de j a myprogram em cada iteração, mas o valor de j pode mudar entre a chamada para myprogram -options e o final do arquivo EOF .

Você tem alguma sugestão?

    
por Andrew 08.07.2012 / 01:01

3 respostas

14

Para quase todos os programas, echo $i | myprogram -options e myprogram -options <<<$i devem funcionar, alimentando o programa $i através da entrada padrão.

<foo usará o conteúdo do arquivo chamado foo como stdin.

<<foo usará o texto entre isso e uma linha que consiste apenas em foo como entrada padrão. Este é um documento aqui (heredoc), como disse Gilles; EOF não significa realmente 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 de herestring , pois usa uma string curta em contraste com um bloco inteiro, como em um heredoc. Herestrings trabalham em bash, mas não em /bin/sh .

    
por 08.07.2012 / 01:15
9

A sintaxe recomendada por este site é chamada de aqui documento . A entrada para o programa de arquivo começa imediatamente abaixo da linha contendo <<EOF , e não é terminada no final do script, mas por uma linha contendo 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 de 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
    
por 08.07.2012 / 01:09
3

aqui documentos como mencionado por Kevin e Gilles acima, ou tubulação simples funcionará em muitos casos.

Para situações mais complicadas, você pode querer olhar para Expect ou similar (por exemplo, o módulo Expect :: CPAN simples é muito fácil de usar a implementação perl). Pessoalmente, eu prefiro o módulo perl (espere em si é tcl), mas existem implementações para muitas linguagens de script comuns. É até possível escrever uma implementação primitiva very da idéia em sh ou bash usando while e read.

A idéia geral de ferramentas Expect e similares é aguardar uma cadeia especificada ou padrão na saída de um programa e, em seguida, alimentá-lo com qualquer entrada desejada.

Um exemplo comum de uso é automatizar o login, "aguardando" (isto é, esperando) a string "ogin:", enviar o login-name, esperar a string "word:" e enviar a senha.

Uma última opção, se você tiver a fonte do myprogram, é apenas modificá-la para receber a entrada que deseja dar como uma opção de linha de comando. Isso pode ser um pouco mais trabalhoso, mas será muito menos agravante do que mexer com os dados Esperar ou canalizar para um programa que não foi projetado para ser usado dessa maneira.

... e não se esqueça de enviar seu patch para meu programa de volta ao upstream :) Mesmo que eles não gostem da maneira como você o codificou, eles podem gostar da ideia o suficiente para adicionar o recurso. Os desenvolvedores de upstream tendem a apreciar as pessoas que saem de suas bundas e contribuem em vez de exigir ou reclamar.

    
por 08.07.2012 / 15:41