为什么将stderr与stdout交换的指令是向后的



在数字室中,我发现有人建议您可以用stdout交换stderr,如下所示:

命令3>&2 2>&1>&3

这反过来看。如果我们发送3到2,然后立即发送2到1(现在看起来是同时发送3和2到1)。我认为IO重定向有一些基本的我不理解的地方,但我找不到任何东西来澄清它

您可以在http://www.catonmat.net/blog/bash-one-liners-explained-part-three/,第21节:

$command 3>&1>&2 2>&3在这里,我们首先将文件描述符3复制到是stdout的副本。然后我们将stdout复制为stderr的副本,最后我们将stderr复制为文件描述符3的副本,即stdout。因此,我们交换了stdout和stderr。

在给出的链接中有更多细节和图片。关键见解是:

3>&1的意思是"3点到1所指向的位置"。然后1>&2说"现在1指向2所指向的位置"(1现在指向流2,但3没有跟随…),最后2>&3说"现在2指向3所指向的地方(即流1)

图示(但请参阅链接-它比我的ascii艺术要好得多):

0 --> /dev/tty0
1 --> /dev/tty1
2 --> /dev/tty2

3>&1:之后

0 --> /dev/tty0
1 --> /dev/tty1
2 --> /dev/tty2
3 --> /dev/tty1

1>&2:之后

0 --> /dev/tty0
1 --> /dev/tty2
2 --> /dev/tty2
3 --> /dev/tty1

2>&3:之后

0 --> /dev/tty0
1 --> /dev/tty2
2 --> /dev/tty1
3 --> /dev/tty1

如您所见,12已经交换。同一链接建议使用3>&-关闭临时流3

啊,我从来没见过。。。。无论如何这似乎本质上是在说。。。将3发送到2…的地址。。。。然后将两个发送到1…的地址。。。。然后将一个发送到3的地址…从第一步开始,我们就知道这是两个的原始地址。。。所以你交换了它们。。。。但我自己还没有测试过。。。。

它之所以向后看,是因为它向后看。

当您看到2>&1时,它看起来像是在向stdout(1)发送stderr(2)。它似乎是这样工作的,程序写入stderr的数据到达stdin管道中的下一个程序。但它并不是这样实现的。该实现将stdout文件描述符(1)的内容分配给stderr文件描述符(2),这样,当程序写入stderr或stdout时,数据就会到达同一位置。

让我们发明一种替代的、虚构的语法。文件描述符是名称为stdinstdoutstderrfd3fd4等的变量,并且按照传统方式从右到左进行分配。

在我们的虚构语法中,stderr = stdout对应于";向后";shell语法CCD_ 18。因为>指向右边,所以看起来赋值指向右边,对吧?错误的这是一个从右到左的任务。

因此,令人困惑的、向后看的3>&2 2>&1 1>&3通过一个临时变量变成了一个简单的交换:

fd3 = stderr
stderr = stdout
stdout = fd3

添加3>&-以关闭临时类似于添加fd3 = null

最新更新