是否可以将文件描述符 3 重定向到一个变量?

Is it possible to redirect file descriptor 3 to a variable?

function f()
{
    echo "normal message" >&1
    echo "error message" >&2
    echo "special message" >&3
}

是否可以这样调用 f,使 stdout 和 stderr 根本不被重定向,并且文件描述符 3 的输出存储在一个变量中?我知道使用临时文件是可能的:

f 3> /tmp/file
variable=$(cat /tmp/file)

但是没有临时文件可以吗?

Is it possible to call f in such a way that stdout and stderr are not redirected at all and output of file descriptor 3 is stored in a variable?

没有。您不能将文件描述符重定向到变量,因为变量内容必须在另一个进程执行过程中被修改,与当前 shell 正在执行的操作同时进行。 IE。您可以使用另一个进程来完成此操作,该进程将从文件描述符读取的数据流式传输到该进程与 shell 之间的某个共享内存中,然后 shell 将在扩展变量时读取该共享内存内容。我相信你可以修补 bash 来支持这样的设置。

但是还是做一个函数而不是硬编码>&3:

log() {
    variable+="$("$@")"$'\n'
}
log echo "special message"

或更好(或更糟)如果您打算在当前 shell 中执行进程,而不是在子shell 中执行进程:

log() {
   logtmpfile=$(tmpfile)
   "$@" > "$logtmpfile"
   variable+="$(<"$logtmpfile")"$'\n'
   rm "$logtmpfile"
}

But is it possible without a temp file?

最好不要。文件是在异步进程之间进行同步的最简单方式。 (有一种 hacky-hacky 方法依赖于管道中的缓冲 exec 3<> >(sleep infinity); echo 123 >&3; timeout 0.1 cat <&3 但它会 fail/block 以意想不到的方式。

我刚找到这个语法:

{ variable=$(f 4>&1 1>&3 3>&4); } 3>&1

这似乎得到了我想要的结果。

当然,我表达问题的方式:“以这样一种方式,即 stdout 和 stderr 根本不被重定向”在这里并不适用,但我真正想要的只是单独文件描述符上的 stdout 和 stderr。出于这个原因,我将保留 KamilCuk 的答案,但我想 post 在这里以防其他人需要它。