Bash/csh: проверка конца файла (EOF) стандартного ввода
Я хотел бы сделать:
if not eof(stdin):
pass stdin to program
else:
do nothing
У меня есть ощущение, что это может быть написано довольно близко к:
if test ! --is-eof - ; then
exec program
Проблема, которую я пытаюсь решить, состоит в том, что program
читает из стандартного ввода, но вылетает, если не получает ввода. У меня нет доступа к источнику для program
таким образом program
не может быть изменено Двоичный ввод больше, чем объем памяти, поэтому ввод stdin в файл сначала недопустимо медленен. Строковая обработка всех входных данных в bash также недопустимо медленная.
В идеале решение должно работать как под csh, так и под bash.
5 ответов
Кажется, что это работает как в csh, так и в bash, и прекрасно справляется с двоичным вводом (также \0 в качестве первого символа):
# 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
Спасибо @glenn-jackman за идею почитать немного перед тем, как пропустить этот и остальную часть stdin через cat
,
Попробуйте сначала прочитать строку из stdin:
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
Если вы не хотите, чтобы ваш скрипт блокировался при попытке найти что-то для чтения, вы можете (по крайней мере, в bash) использовать чтение с тайм-аутом
$ ( read -t 0 var ; echo $? )
1
$ echo foo | ( read -t 0 var ; echo $? )
0
Это, однако, не гарантирует, что у вас есть EOF, но что сейчас нечего читать
Какой ввод ожидает ваша программа? вы передаете вывод из одной программы в другую или он читает файл?
Если вы используете перенаправление канала для сбора входных данных в свой скрипт, то он будет выполняться до тех пор, пока не будет предоставлена входная информация.
если вы пытаетесь читать из файла, используйте "while" или "then" для выполнения работы.
Я пишу здесь, так как это возникло при поиске, и так как это помогло мне отладить на Darwin (Snow Leopard) Bash в set -x;trap 'test -s /dev/stdin||exit' debug
чтобы найти вызов, который потреблял унаследованный ввод родительского сценария.
Для слабонервных:
if [[ -s /dev/fd/0 ]]
then echo 'Not at EOF'
else echo 'Currently no input to read'
fi
Тестовое задание:
echo $((echo|test -s /dev/stdin)&&! (true|test -s /dev/stdin)&&echo pass||echo fail) ${BASH_VERSINFO[*]}
Приведенный выше тест выдает следующее в моих версиях и системах 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
Трубопровод к cat /proc/self/fdinfo/0
на моем Debian (wheezy) ничего не дает для проверки.
CheerIO или, вернее, cheerEO для ошибочных /% выхода)