fin*_*oot 5 scripting bash pipe stdin read
我不是在寻找该问题的变通方法或解决方案。我很好,它在bash
. 我只是不明白为什么它不起作用。
我正在寻找为什么以下脚本不起作用的深入答案。所有以前的互联网搜索结果,包括来自 unix.stackexchange.com 的帖子,都无法真正完全清除这一点。它与read
读取有关,stdin
它不起作用,因为stdin
已经通过管道cat
喂食“采取”(?)bash
?
示例 bash 脚本test.sh
:
echo "Please say name:"
read NAME
echo "Hello $NAME"
Run Code Online (Sandbox Code Playgroud)
方法 1 调用脚本bash test.sh
:
$ bash test.sh
Please say name:
XYZ
Hello XYZ
$
Run Code Online (Sandbox Code Playgroud)
方法 2 通过管道运行脚本bash
:
$ cat test.sh | bash
Please say name:
$
Run Code Online (Sandbox Code Playgroud)
因此脚本立即返回到提示,无需等待输入甚至打印第二行。
您确实使用读取了标准输入read
,但是您读取的是标准输入的下一行 - 即echo "Hello $NAME"
. 读完那行后,没有更多的输入,所以没有更多的命令要执行,脚本就结束了。
目前只有一个标准输入流,并且你想使用它的代码和数据。这与交互式bash
会话从您的输入、read
响应以及您运行的任何其他想要使用标准输入的命令中读取命令的方式相同。
如果我们在脚本末尾添加额外的一行,您可以看到这种情况发生:
echo "Please say name:"
read NAME
echo "Hello $NAME"
printf 'name=%s\n' "$NAME"
Run Code Online (Sandbox Code Playgroud)
这两者都提供了一个进一步的命令来查看脚本继续执行,并向我们展示了读入的内容NAME
:
Please say name:
name=echo "Hello $NAME"
Run Code Online (Sandbox Code Playgroud)
您可以看到该变量逐字保存了脚本文件中写入的内容 - 没有发生变量插值、执行或扩展。
如果你想read
从终端,这是可能的。可能有效的最简单方法是从标准输出而不是标准输入 (!) 中读取,它可能连接到 TTY:
read NAME <&1
Run Code Online (Sandbox Code Playgroud)
这将等待我输入一些内容,然后继续执行程序的其余部分。您也可以使用/dev/tty
或$(tty)
。