我有点困惑
$ bash <<EOF
read -p 'This will not work' input
EOF
因为
$ cat script
read -p 'This will work fine' input
$ bash script
This will work fine
有什么不同?它似乎是一种标准行为,因为ash
的行为方式完全相同。
根据目前为止提供的答案,我怀疑(然后确认)以下工作。我认为这实际上是我一直想做的事情,但<()
语法总是我忘记存在的语法。
$ bash <( cat <<EOF
read -p 'This works' input
EOF
)
由于read
是bash内置的,它如上所述继承了bash
的stdin。在第一种情况下,bash
将此文档作为stdin(或更专业地,文件描述符0),并且没有任何内容可供read
阅读。
read
只从stdin(fd0
)读取,而在第二种情况下,bash
打开另一个文件描述符而不是stdin从script
读取脚本,这与传递给read
的stdin不冲突,因此read
可以按预期工作。
你可以尝试这个测试。
$ bash << EOF ls -l /proc/$$/fd EOF
和
$ cat script.sh ls -l /proc/$$/fd $ bash script.shThe difference is apparent if you compare the outputs from samples bove.
你不能每个进程同时有多个stdin
,所以这里作为输入传递给bash
的文件不能包含read -p
。
使用bash script
,正在运行的script
是Bash shell的子进程,并且stdin
没有并发read
,因此它将按预期工作。
在这两种情况下,read
命令都从执行它的bash
进程继承其标准输入。
在第一个示例中,这意味着实际包含read
命令的here文档。根据bash
已经读取的文档的数量(通常是全部),read
无需读取任何内容,因此它以非零退出状态退出。
在第二个示例中,bash
在不同的文件描述符上打开命名文件。 read
仍然继承了bash
进程的标准输入,但这次bash
根本没有读取它,所以read
命令获得下一个可用的行。这里的标准输入是终端,因此read
会阻塞,直到用户输入一行。
最简单的解决方案是将交互式命令写入临时文件,然后获取临时文件:
cat <<'_EOF_' >/tmp/$$.sh
read -p 'This is an interactive command, please enter a string: ' STRING
_EOF_
# Command in temporary file get executed here
source /tmp/$$.sh
echo "STRING= '$STRING'"