如何将tee操作用于fd而不是命名管道

7

我希望能够使用三个不同的程序分析进程的标准输出。目前,我已经成功地使用了命名管道,但是是否可以使用文件描述符实现呢?

以下是目前能够正常工作的代码:


exec 3< <(myprog)
tee p1 p2 >/dev/null <&3
cat p1|ap1 & cat p2|ap2 &

其中,p1和p2是通过mkfifo创建的管道文件,而ap1和ap2则是用来进行分析的程序。我不确定我是否表述得正确,但是否有一种方法可以将tee命令输出到两个新的文件描述符中呢?类似于这样:


exec 3< <(myprog)
tee >&4 >&5 <&3
cat <&4|ap1 & cat <&5|ap2 &
1个回答

7
你差点就做到了:
myprog | tee >(ap1) >(ap2) >(ap3) >/dev/null

请注意,ap1可以是一个函数。如果您希望该函数可以访问脚本的参数,请使用"$@"来调用它,即:
ap1 () {
  # here the script arguments are available as $1, $2, ...
}
# ditto for ap2, ap3
myprog | tee >(ap1 "$@") >(ap2 "$@") >(ap3 "$@") >/dev/null

如果您的shell不支持>()(bash、ksh和zsh支持,但这不是POSIX标准),但您的操作系统支持/dev/fd(包括Solaris、Linux、*BSD、OSX和Cygwin在内的大多数Unix系统都支持),您可以使用显式文件描述符重定向。
{ { { myprog | tee /dev/fd/3 /dev/fd/4 |
      ap1 >&2
    } 3>&1 |
    ap2 >&2
  } 4>&1 |
  ap3 >&2
}

啊,那可能行得通。不过有没有办法将tee到fd呢?ap1和ap2是带有管道和大量开关的巨大命令。如果我能使用fd,阅读起来会更容易些。 - User1
@User1:这绝对是可能的(并且具有在不支持<()>()的shell中工作的优点),但语法很笨拙。在这里,将ap1ap2定义为函数会更简单。 - Gilles 'SO- stop being evil'
其他语法是什么?我刚刚注意到,在脚本的某些部分中,我使用if语句根据输入参数修改如何调用ap1。在我的情况下,>()可能不太适用。但我不知道还有什么其他方法可以调用它。有什么想法吗?非常感谢你迄今为止的帮助。 - User1
@User1:你可以很容易地将参数传递给函数,看看我的编辑。这里是如何在不使用>()的情况下完成它;但你要为了可移植性而这样做,而不是为了可读性!我坚持认为,在你的情况下,函数是最好的选择。 - Gilles 'SO- stop being evil'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接