我通常if [ -t 0 ]
用来测试标准输入并if [ -t 1 ]
查看标准输入和标准输出是否是 TTY,如果不是,我假设它们是管道。我最近了解到这是一个糟糕的假设:
function context()
{
if [ -t 0 ]
then
if [ -t 1 ]
then
echo "no pipes"
else
echo "pipe out only"
fi
else
if [ -t 1 ]
then
echo "pipe in only"
else
echo "pipe in and out"
fi
fi
}
echo "No Loop:" # these cases work as desired
context
echo 'f' | context
echo 'f' | context | cat
context | cat
echo
echo "Loop:"
echo $'foo
bar' | while read x
do
context # I want this to say "no pipes"
echo 'f' | context
done
上面 bash 的输出是这样的:
No Loop:
no pipes
pipe in only
pipe in and out
pipe out only
Loop:
pipe in only
pipe in only
pipe in only
pipe in only
如何更改 to 的定义,context
以便第 5 次和第 7 次调用打印“无管道”?
也就是说,我不想测试标准输入是否不是终端(这会导致问题),而是测试这个特定函数的标准输入是否恰好是管道。我看到它-p
检查它是否是命名管道,但我希望它用于匿名管道。
编辑
实际用例涉及我们将调用的函数theDb
来代替context
. 理想情况下,无论上下文如何,以下两种情况都是等效的:
cat file_with_some_sql | theDb
theDb "sql goes here"
“仅管道”出现四次的原因实际上是因为该
context
功能正常工作,并且echo $'foo bar' | while read x
等是管道 -循环中的所有内容都while
从管道获取输入。要获得所需的输出,请将循环更改为while
循环for
,并且不要将任何内容通过管道传输到该for
循环:输出:
为了显示 OP 代码出错的地方,只需将一些东西放入
for
循环中,看看会发生什么:输出:
新手可能(错误地)认为它
while read x
消耗了所有标准输入,但不一定如此。考虑这个例子,read
里面有一个while
循环:输出: