![带重定向的 bash 命令替换:错误的文件描述符](https://linux22.com/image/119101/%E5%B8%A6%E9%87%8D%E5%AE%9A%E5%90%91%E7%9A%84%20bash%20%E5%91%BD%E4%BB%A4%E6%9B%BF%E6%8D%A2%EF%BC%9A%E9%94%99%E8%AF%AF%E7%9A%84%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6.png)
以下命令在 dash 中有效,但在 bash 中失败,并显示“错误文件描述符”。
$ dash -c 'out=$(echo "to fd3" >&3; echo "to stdout") 3>&1; echo "out: $out"'
to fd3
out: to stdout
$ bash -c 'out=$(echo "to fd3" >&3; echo "to stdout") 3>&1; echo "out: $out"'
bash: 3: Bad file descriptor
out: to stdout
当我用子 shell 替换命令替换时,它似乎可以在 dash 和 bash 中工作。
$ dash -c '(echo "to fd3" >&3; echo "to stdout") 3>&1'
to fd3
to stdout
$ bash -c '(echo "to fd3" >&3; echo "to stdout") 3>&1'
to fd3
to stdout
版本:
$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-unknown-linux-gnu)
不知道如何获得破折号版本。我系统上的手册页日期为 2003 年 1 月 19 日。
研究:
我查了一下 bash 和 dash 是如何执行命令的。这就是我发现的。
对于bash:https://www.gnu.org/software/bash/manual/bashref.html#Shell-Operation
对于破折号:http://man7.org/linux/man-pages/man1/dash.1.html(“简单命令”部分)
据我了解,两者都在重定向之前进行扩展。命令替换是一种扩展。因此,在命令替换中未设置文件描述符 3 是有道理的。
为什么它在破折号中起作用?为什么它在 bash 中不起作用?这是破折号的错误吗?还是bash?它到底是一个有效的构造吗?
答案1
重定向是在赋值扩展之前还是之后执行当没有命令时 POSIX 未指定,因此两者都是有效的,您都不能依赖其中任何一个。因此,为了便于携带,您需要:
{ out=$(echo "to fd3" >&3; echo "to stdout"); } 3>&1
AT&Tksh
和 Bourne shell 的行为类似于bash
;zsh
, pdksh
,yash
的行为dash
与本例类似。