为什么cat退出shell脚本,但仅当它';它是用管子喂的?

为什么cat退出shell脚本,但仅当它';它是用管子喂的?,shell,sed,sh,cat,Shell,Sed,Sh,Cat,为什么cat退出shell脚本,但仅当它由管道馈送时才退出 以这个名为“foobar.sh”的shell脚本为例: 以及一个名为“foo.txt”的文本文件,其中只包含一行: foo 现在,如果我在命令行中键入/foobar.sh foo.txt,那么我将获得以下预期输出: 1 foo.txt foo bar 但是,如果我键入cat foo.txt |/foobar.sh,那么令人惊讶的是,我只得到以下输出: 0 foo 我不明白。如果$#报告的参数数为零,那么cat$1如何仍然返回fo

为什么cat退出shell脚本,但仅当它由管道馈送时才退出

以这个名为“foobar.sh”的shell脚本为例:

以及一个名为“foo.txt”的文本文件,其中只包含一行:

foo
现在,如果我在命令行中键入
/foobar.sh foo.txt
,那么我将获得以下预期输出:

1
foo.txt
foo
bar
但是,如果我键入
cat foo.txt |/foobar.sh
,那么令人惊讶的是,我只得到以下输出:

0

foo
我不明白。如果
$#
报告的参数数为零,那么
cat$1
如何仍然返回
foo
?既然如此,既然$1显然是
foo
,为什么sed-e的| foo | bar | g'$1不返回任何东西呢

这看起来很像一只虫子,但我认为它是魔法。请解释

更新

根据给定的答案,以下脚本给出了预期的输出,假设为一行foo.txt:

#! /bin/sh
if [ $# ]
then
yay=$(cat $1)
else
read yay
fi
echo $yay | cat
echo $yay | sed -e 's|foo|bar|g'

当您不给
cat
提供参数时,它从stdin读取。如果未给出
$1
,则
cat$1
与简单的
cat
相同,它读取您输入的文本(
cat foo.txt


然后运行
sed
命令,与
cat
一样,它从stdin读取,因为它没有filename参数
cat
已经消耗了所有stdin。没有剩余的内容可供阅读,因此
sed
退出而不打印任何内容。

当您没有为
cat
提供参数时,它从stdin读取。如果未给出
$1
,则
cat$1
与简单的
cat
相同,它读取您输入的文本(
cat foo.txt

然后运行
sed
命令,与
cat
一样,它从stdin读取,因为它没有filename参数
cat
已经消耗了所有stdin。没有什么可以读的了,所以sed没有打印任何东西就退出了。

不,$1不是“foo”$1是

即,未定义/无

与编程语言不同的是,shell中的变量被相当简单地替换,生成的命令以文本方式执行(好吧,有点类似)。在这种情况下,“cat$1”变成“cat”,它将从stdin获取输入。这对您的执行非常方便,因为您已经通过管道在stdin上提供了“foo”

看看发生了什么

sed同样将从stdin读取,但已经在流的末尾,所以退出。

否,$1不是“foo”$1是

即,未定义/无

与编程语言不同的是,shell中的变量被相当简单地替换,生成的命令以文本方式执行(好吧,有点类似)。在这种情况下,“cat$1”变成“cat”,它将从stdin获取输入。这对您的执行非常方便,因为您已经通过管道在stdin上提供了“foo”

看看发生了什么


sed同样将从stdin读取,但已经在流的末尾,所以退出。

好的,但我如何知道通过stdin发送了什么?有环境变量吗?没有。您可能会玩一些有趣的游戏,但通常只有流的消费者才能看到流中的内容。把它想象成一个文字管道。你把一些东西塞进一端,它们从另一端出来。里面发生的事情是不透明的,你在里面看不到。我可以使用read命令将stdin分配给var,然后从那里开始。我已经更新了我的问题…好的,但是我怎么知道什么是通过stdin发送的呢?有环境变量吗?没有。您可能会玩一些有趣的游戏,但通常只有流的消费者才能看到流中的内容。把它想象成一个文字管道。你把一些东西塞进一端,它们从另一端出来。里面发生的事情是不透明的,你在里面看不到。我可以使用read命令将stdin分配给var,然后从那里开始。我已经更新了我的问题。。。
#! /bin/sh
if [ $# ]
then
yay=$(cat $1)
else
read yay
fi
echo $yay | cat
echo $yay | sed -e 's|foo|bar|g'