为什么在将脚本通过管道传输到 bash 时无法使用“read”从“stdin”读取?

为什么在将脚本通过管道传输到 bash 时无法使用“read”从“stdin”读取?

我并不是在寻找解决该问题的方法或解决方案。我很高兴它不像在 中那样工作bash。我只是不明白为什么它不起作用。

我正在寻找一个深入的答案,为什么以下脚本不起作用。之前所有的互联网搜索结果,包括来自 unix.stackexchange.com 的帖子,都无法真正完全清除这个问题。它与read读取stdin不起作用有关,因为stdin已经通过管道cat馈送“获取”(?)?bash

bash 脚本示例test.sh

echo "Please say name:"
read NAME
echo "Hello $NAME"

方法 1 调用脚本bash test.sh

$ bash test.sh
Please say name:
XYZ
Hello XYZ
$

方法 2 通过管道运行脚本bash

$ cat test.sh | bash
Please say name:
$

因此脚本立即返回到提示符,无需等待输入,甚至无需打印第二行。

答案1

做过从 stdin 读取read,但您读取的是标准输入的下一行 - 即echo "Hello $NAME".读完该行后,没有更多的输入,因此没有更多的命令要执行,脚本就结束了。

只有一个标准输入流,并且您尝试将其用于代码和数据。这与交互式bash会话从您的键入中读取命令、read响应以及您运行的任何其他命令想要使用标准输入的方式相同。

如果我们在脚本末尾添加额外的一行,您可以看到这种情况发生:

echo "Please say name:"
read NAME
echo "Hello $NAME"
printf 'name=%s\n' "$NAME"

这既提供了进一步的命令来查看脚本继续执行,并向我们展示了读入的内容NAME

Please say name:
name=echo "Hello $NAME"

你可以看到变量保持逐字脚本文件中写入的内容 - 没有发生变量插值、执行或扩展。


如果你想read从终端,这是可能的。最简单的可行方法是从标准输出而不是标准输入 (!) 读取,标准输入可能连接到 TTY:

read NAME <&1

这将等待我输入一些内容,然后继续执行程序的其余部分。您也可以使用/dev/tty$(tty)

相关内容