带有重定向的 bash 命令替换:错误的文件描述符

les*_*ana 4 bash io-redirection dash command-substitution

以下命令在 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
Run Code Online (Sandbox Code Playgroud)

当我用子外壳替换命令替换时,它似乎可以在 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
Run Code Online (Sandbox Code Playgroud)

版本:

$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-unknown-linux-gnu)
Run Code Online (Sandbox Code Playgroud)

不知道如何获得破折号版本。我系统上的手册页日期为 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 中不起作用?这是破折号中的错误吗?还是重击?它是一个有效的构造吗?

Sté*_*las 7

当没有 command 时POSIX 未指定是在赋值扩展之前还是之后执行重定向,因此两者都是有效的,您不能依赖其中任何一个。所以便携,你需要:

{ out=$(echo "to fd3" >&3; echo "to stdout"); } 3>&1
Run Code Online (Sandbox Code Playgroud)

AT&Tksh和 Bourne shell 的行为类似于bash; zsh, pdksh,在这种情况下yash表现得像dash