Bash 块重定向和管道

Bash 块重定向和管道

我正在学习 bash 重定向。我希望下面的代码能够完成与ls | grep foo | grep bar.

#!/bin/bash                                                                     

{
    {
        ls | grep foo
    } 2>&1 1>&4 | grep bar
} 4>&1

这匹配 foo 但不匹配 foo 和 bar。我认为这会起作用,因为将2>&1fd 1 中的管道复制到 fd 2,然后我们将 fd 1 重置为标准输出。

您可以在保留大括号(上下文)的同时修复此代码吗?如果我删除2>&1 1>&4它,它会按预期工作。但我想学习。

我认为在管道的左侧|它只需要 stdout,所以即使我将管道复制到 fd 2,它仍然只会在管道的左侧查找 fd 1。

参考:https://wiki.bash-hackers.org/howto/redirection_tutorial#an_example

在上面引用的链接中,有一个图表,其中 cmd1 的 fd 2 指向 cmd3 的 fd 0。我正在尝试用我的例子来验证这一点。

答案1

你的尝试:

{
    {
        ls | grep foo # goes to stdout (fd 1)
    } 2>&1 1>&4 | grep bar  # at this level: 2 now points to where fd1 is pointing (stdout), and 1 is *then* directed to the new fd 4 (ie to stdin of the outside curly)
} 4>&1  ## at this shell 'level', a new fd 4 is now pointing to where 1 is pointing: stdout

:因此 grep 栏仅在 { ls | 的 stderr 上完成grep foo },因此在一个空的标准输入上,作为 { ls | 的唯一标准错误grep foo } 转到 { ls | grep foo } 的标准输出grep foo }.这永远不会看到文件名。 ths 文件名转到 fd 4 尝试:

{
    {
        ls | grep foo
    } 2>&1 1>&4
} 4>&1 | grep bar

或者

{
    {
        ls | grep foo
    } 2>&1 1>&4 | <&4 grep bar
} 4>&1

并比较...

注意:如果您想让内部命令的 stderr 也转到 stdout,则需要将其复制到第二个位置: 1>&4 2>&1 [即:1 现在转到 fd 4,然后 2 转到 1 所在的位置现在指向,即 fd 4 以及]

答案2

据我所知,以下情况属实。

{
    {
        ls | grep foo
    } 2>&1 1>&4 | grep bar
} 4>&1

相当于

(ls | grep foo 2>&1 1>&4 | grep bar) 4>&1

它会失败,因为 fd 4 是 /dev/pts/0,而 1>&4 将导致 fd 1 具有相同的 /dev/pts/0 而不是管道。

答案3

看来您希望重定向来复制数据?考虑使用tee.当你学习的时候,我不会说更多破坏事情的。

也可用于shellcheck检查您的代码。它将帮助您更快地找到大多数错误。

相关内容