Bash/csh:测试 stdin 的文件结尾 (EOF)

Bash/csh:测试 stdin 的文件结尾 (EOF)

我想要做:

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

我感觉它可以写得相当接近:

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

我试图解决的问题是,它program从 stdin 读取,但如果没有输入就会崩溃。我无法访问源代码,因此program无法program更改。二进制输入大于内存大小,因此首先将 stdin 放入文件的速度慢得令人无法接受。在 bash 中逐行处理所有输入的速度也慢得令人无法接受。

理想情况下,该解决方案应该可以在 csh 和 bash 下运行。

答案1

这似乎在 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

答案2

首先尝试从标准输入读取一行:

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

答案3

如果你不想让你的脚本在尝试寻找要读取的内容时被阻止,你可以(至少在 bash 中)使用带超时的读取

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

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

然而,这并不能保证你有 EOF,只是目前没有任何内容可读

答案4

我在这里发帖是因为这是在搜索时出现的,并且它对我有帮助调试达尔文(雪豹)狂欢找到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

在我的 Debian(wheezy)上通过管道传输cat /proc/self/fdinfo/0也没有任何结果可以测试。

CheerIO 或者 cheerEO 表示错误/输出 %)

相关内容