Bash / csh: teste de fim de arquivo (EOF) de stdin

2

Eu gostaria de fazer:

if not eof(stdin):
   pass stdin to program
else:
   do nothing

Eu tenho a impressão de que pode ser escrito bem perto de:

if test ! --is-eof - ; then
  exec program

O problema que estou tentando resolver é que program lê stdin, mas falha se não receber entrada. Eu não tenho acesso à fonte para program , portanto program não pode ser alterado. A entrada binária é maior que o tamanho da memória, portanto, colocar stdin em um arquivo primeiro é inaceitavelmente lento. Processar toda a entrada linha por linha no bash é inaceitavelmente lento também.

A solução deve idealmente funcionar tanto em csh quanto em bash.

    
por Ole Tange 20.12.2012 / 10:11

5 respostas

1

Isto parece funcionar tanto no csh quanto no bash e funciona bem com a entrada binária (também \ 0 como primeiro char):

# Set $_FIRST_CHAR_FILE to the name of a temp file.
eval 'echo $SHELL | grep -E "/(t)?csh" > /dev/null && echo setenv _FIRST_CHAR_FILE /tmp/$$.first_char_file || echo export _FIRST_CHAR_FILE=/tmp/$$.first_char_file'

dd bs=1 count=1 of=$_FIRST_CHAR_FILE >&/dev/null
test -s "$_FIRST_CHAR_FILE" && ( cat $_FIRST_CHAR_FILE; rm $_FIRST_CHAR_FILE; cat - ) | program

Obrigado a @glenn-jackman por dar a ideia de ler um pouco antes de passar isso e o resto do stdin através de cat .

    
por 22.12.2012 / 18:07
1

Tente ler uma linha do stdin primeiro:

IFS= read -r line
if [[ -n "$line" ]]; then
    # the line is non-empty.
    # add the line back into the stream and pipe it into your program
    { echo "$line"; cat -; } | your_program
fi
    
por 20.12.2012 / 17:04
0

Que tipo de entrada seu programa espera? você está canalizando a saída de um programa para o outro ou está lendo um arquivo?

Se você estiver usando o redirecionamento de pipe para coletar entrada para o script ur, ele continuará executando até que o fornecimento de entrada seja fornecido.

se você estiver tentando ler de um arquivo, use "while" ou "until" para fazer o trabalho.

    
por 20.12.2012 / 13:20
0

Eu postei aqui desde que isso surgiu ao pesquisar e desde que isso me ajudou a depurar em Darwin (snow leopard) bash em set -x;trap 'test -s /dev/stdin||exit' debug para encontrar uma chamada que estava consumindo a entrada herdada do script pai.

Para os fracos de coração:

if [[ -s /dev/fd/0 ]]
    then echo 'Not at EOF'
    else echo 'Currently no input to read'
fi

Teste:

echo $((echo|test -s /dev/stdin)&&! (true|test -s /dev/stdin)&&echo pass||echo fail) ${BASH_VERSINFO[*]}

O teste acima produz o seguinte nas minhas versões e sistemas bash.

pass 4 2 45 2 release i386-apple-darwin10.8.0
pass 3 2 48 1 release x86_64-apple-darwin10.0
fail 4 2 37 1 release x86_64-pc-linux-gnu

Piping para cat /proc/self/fdinfo/0 no meu Debian (wheezy) não dá nada para testar.

CheerIO ou melhor, cheerEO para Erroneous / Output%)

    
por 09.06.2014 / 11:57
0

Se você não quiser que seu script bloqueie na tentativa de procurar algo para ler, você pode (pelo menos no bash) usar uma leitura com tempo limite

$ ( read -t 0 var ; echo $? )
1

$ echo foo | ( read -t 0 var ; echo $? )
0

No entanto, isso não garante que você tenha EOF, mas não há nada para ler no momento

    
por 14.04.2015 / 09:58

Tags