ChatGPT解决这个技术问题 Extra ChatGPT

如何在将标准输出保持在屏幕上的同时通过管道传输它? (而不是输出文件)

我想管道程序的标准输出,同时将其保留在屏幕上。

举个简单的例子(这里使用的 echo 仅用于说明目的):

$ echo 'ee' | foo
ee <- 我想看到的输出

我知道 tee 可以将标准输出复制到文件中,但这不是我想要的。
$ echo 'ee' | tee output.txt | foo

我试过
$ echo 'ee' | tee /dev/stdout | foo 但它不起作用,因为到 /dev/stdout 的 tee 输出通过管道传输到 foo

请注意,虽然 echo 'ee' | tee /dev/stderr 有效,所以如果您的 “在屏幕上” 要求也被 stderr 满足,那就可以了。

j
jlliagre

这是一个适用于任何 Unix/Linux 实现的解决方案,假设它关心遵循 POSIX 标准。它也适用于一些非 Unix 环境,例如 cygwin

echo 'ee' | tee /dev/tty | foo

参考:The Open Group Base Specifications Issue 7 IEEE Std 1003.1, 2013 Edition, §10.1

/dev/tty 与该进程的进程组相关联,如果有的话。无论输出如何重定向,它对于希望确保向终端写入消息或从终端读取数据的程序或 shell 过程很有用。它也可以用于要求输出文件名的应用程序,当需要键入输出并且查找当前正在使用的终端很烦人时。在每个进程中,控制终端的同义词

据报道,某些环境(如 Google Colab)未实施 /dev/tty,但仍让其 tty 命令返回可用设备。这是一种解决方法:

tty=$(tty)
echo 'ee' | tee $tty | foo

或使用古老的 Bourne 贝壳:

tty=`tty`
echo 'ee' | tee $tty | foo

@AsyaKamsky问题是关于在屏幕上输出的进程。这首先排除了与任何屏幕分离的 cron 作业。
@static_rtti 为什么你年复一年地忽略我对你评论的回复?
@PaulBissex /dev/tty 是必需的 Unix 设备。您是否在 BSD 监狱中运行?
@PaulBissex 这要么是一个实现,要么是一个配置错误。 /dev 挂载了吗?什么显示“ls -l /dev/tty /dev/tty* /dev”?请参阅lists.freebsd.org/pipermail/freebsd-bugs/2012-November/… forums.freebsd.org/threads/…
您可以像这样将 tee 级联:cat some.log | tee /dev/tty | tee -a other.log | grep -i 'foo' >> foo.log 到 1) 将其全部发送到控制台,2) 将其全部附加到另一个文件中,3) 将 foo 行添加到另一个文件中。
b
bmk

另一件要尝试的事情是:

echo 'ee' | tee >(foo)

>(foo) 是一个 process substitution

编辑:为了更清楚一点,(。)在这里启动一个新的子进程到当前终端,输出被重定向到。

echo ee | tee >(wc | grep 1)
#              ^^^^^^^^^^^^^^ => child process

除了子进程中的任何变量声明/更改不会反映在父进程中之外,在子进程中运行命令几乎没有问题。


如果我想将 foo 的输出通过管道传输到另一个栏怎么办?
@JackTang - 我认为 foo 输出上的任何进一步管道都必须成为流程替换的一部分。这是一个示例:echo 'ee' | tee file.txt >(wc -c | tr -d ' ')
这是我在 FreeBSD 上的解决方案(没有 /dev/tty)
@Nick Chammas,为了保持正常的管道,您可以交换 tee: echo 'ee' | tee >(cat) | foo | bar 的输出。
@Vaelus 对我来说 foo 看到 2x ee 并且终端上没有打印任何内容。尝试 echo 'ee' | tee >(cat) | grep .echo 'ee' | tee >(cat) | grep x
J
Jan

尝试:

$ echo 'ee' | tee /dev/stderr | foo

当然,如果使用 stderr 是一种选择。


u
user51527

在某些系统上拒绝访问“/dev/stdout”,但访问用户终端是由“/dev/tty”提供的。对“foo”使用“wc”,上面的例子可以正常工作(在 linux、OSX 等上):

% 回声“嗨”|三通 /dev/tty |厕所 嗨 1 1 3

要在匹配文件列表的底部添加计数,我使用如下内容:
% ls [A-J]* | tee /dev/tty | wc -l

为了避免记住所有这些,我定义了别名:
% alias t tee /dev/tty
% alias wcl wc -l

所以我可以简单地说:
% ls [A-J]* | t | wcl

后记:对于可能会嘲笑它的发音为“titty”的年轻人,我可能会补充说,“tty”曾经是“电传打字机”终端的常见缩写,它使用一卷黄纸并有圆形键,通常卡住。


M
Michael Martinez

首先,您需要找出与您的屏幕关联的终端(或您希望输出显示的任何屏幕):

tty

然后您可以将输出发送到该终端并通过您的 foo 程序管道另一个副本:

echo ee | tee /dev/pty/2 | foo

oneliner: t=$(tty) echo ee |三通$t |富 |酒吧
@JackTang 确实更好,但 t 没用。您可以使用 echo ee | tee $(tty) | foo,但它仍然有一个无用的命令 (tty),因为 /dev/tty 确实有效。