我在 bash 脚本中输入了一行,并想在将它提供给程序之前检查管道是否有数据。
搜索我找到了,test -t 0但在这里不起作用。总是返回假。那么如何确定管道有数据呢?
例子:
echo "string" | [ -t 0 ] && echo "empty" || echo "fill"
Run Code Online (Sandbox Code Playgroud)
输出: fill
echo "string" | tail -n+2 | [ -t 0 ] && echo "empty" || echo "fill"
Run Code Online (Sandbox Code Playgroud)
输出: fill
与测试上述管道是否产生输出的标准/规范方式不同?需要保留输入以将其传递给程序。这概括了如何将输出从一个进程传送到另一个进程,但仅在第一个进程有输出时才执行?专注于发送电子邮件。
Gil*_*il' 57
无法使用常用的 shell 实用程序查看管道的内容,也无法从管道中读取字符然后将其放回原处。知道管道有数据的唯一方法是读取一个字节,然后您必须将该字节送到其目的地。
所以这样做:读取一个字节;如果检测到文件结束,则在输入为空时执行您想做的操作;如果您确实读取了一个字节,则在输入不为空时分叉您想要执行的操作,将该字节输送到其中,然后输送其余数据。
first_byte=$(dd bs=1 count=1 2>/dev/null | od -t o1 -A n | tr -dc 0-9)
if [ -z "$first_byte" ]; then
# stuff to do if the input is empty
else
{
printf "\\$first_byte"
cat
} | {
# stuff to do if the input is not empty
}
fi
Run Code Online (Sandbox Code Playgroud)
在ifne从实用乔伊赫斯的moreutils如果输入不为空运行的命令。默认情况下通常不会安装它,但它应该可用或易于在大多数 unix 变体上构建。如果输入为空,ifne则不执行任何操作并返回状态 0,这与命令运行成功无法区分。如果你想在输入为空的情况下做一些事情,你需要安排命令不返回0,这可以通过让成功案例返回一个可区分的错误状态来完成:
ifne sh -c 'do_stuff_with_input && exit 255'
case $? in
0) echo empty;;
255) echo success;;
*) echo failure;;
esac
Run Code Online (Sandbox Code Playgroud)
test -t 0与此无关;它测试标准输入是否是终端。它没有以任何方式说明是否有任何输入可用。
小智 24
一个简单的解决方案是使用ifne命令(如果输入不为空)。在某些发行版中,默认情况下不安装它。它是moreutils大多数发行版中软件包的一部分。
ifne 当且仅当标准输入不为空时运行给定的命令
请注意,如果标准输入不为空,则将其传递ifne给给定的命令
mvi*_*eck 19
检查 stdin (0) 的文件描述符是打开还是关闭:
[ ! -t 0 ] && echo "stdin has data" || echo "stdin is empty"
Run Code Online (Sandbox Code Playgroud)
yas*_*hma 14
如果你喜欢简短而神秘的单线:
$ echo "string" | grep . && echo "fill" || echo "empty"
string
fill
$ echo "string" | tail -n+2 | grep . && echo "fill" || echo "empty"
empty
Run Code Online (Sandbox Code Playgroud)
我使用了原始问题中的示例。如果您不希望使用-q带有 grep的管道数据使用选项
小智 10
老问题,但如果有人像我一样遇到它:我的解决方案是超时阅读。
while read -t 5 line; do
echo "$line"
done
Run Code Online (Sandbox Code Playgroud)
如果stdin为空,这将在 5 秒后返回。否则,它将读取所有输入,您可以根据需要对其进行处理。
检查 Unix 中是否有可供读取的数据的一种简单方法是使用FIONREADioctl。
我想不出有任何标准实用程序可以做到这一点,所以这里有一个简单的程序(比ifne来自 moreutils 恕我直言 ;-)更好)。
fionread [ prog args ... ]
Run Code Online (Sandbox Code Playgroud)
如果 stdin 上没有可用数据,它将以状态 1 退出。如果有数据,它将运行prog。如果没有prog给出,它将以状态 0 退出。
这应该适用于大多数类型的文件描述符,而不仅仅是管道。
fionread.c
fionread [ prog args ... ]
Run Code Online (Sandbox Code Playgroud)
在 bash 中:
read -t 0
Run Code Online (Sandbox Code Playgroud)
检测输入是否有数据(不读取任何内容)。然后您可以读取输入(如果在执行读取时输入可用):
if read -t 0
then read -r input
echo "got input: $input"
else echo "No data to read"
fi
Run Code Online (Sandbox Code Playgroud)
注意:理解这取决于时间。这会检测输入是否仅在read -t运行时已有数据。
例如,与
{ sleep 0.1; echo "abc"; } | read -t 0; echo "$?"
Run Code Online (Sandbox Code Playgroud)
输出是1(读取失败,即:空输入)。echo 写入了一些数据,但启动和写入第一个字节的速度不是很快,因此,read -t 0将报告其输入为空,因为程序尚未写入任何内容。
| 归档时间: |
|
| 查看次数: |
82152 次 |
| 最近记录: |