读取 stdin 并通过管道传递到 tee

读取 stdin 并通过管道传递到 tee

我正在玩xinput看键盘事件。我想使用 转换输出awk并将其传递给tee,打印到标准输出并同时写入文件。

我在设备 14 上观看事件,输入单个Space,然后输入Ctrl+C退出:

$ xinput test 14
key release 36
key press   65
 key release 65
key press   37
key press   54
^C

我可以用以下方法来改变它awk

$ xinput test 14 | awk '{ print $NF }'
36
65
 65
37
54
^C

或者我可以将其通过管道传输到tee

$ xinput test 14 | tee a.log
key release 36
key press   65
 key release 65
key press   37
key press   54
^C

$ cat a.log
key release 36
key press   65
 key release 65
key press   37
key press   54

但我无法将转换后的输出通过管道传输到tee

$ xinput test 14 | awk '{ print $NF }' | tee b.log
^C

$ cat b.log

我想我明白发生了什么,并且可以将其归结为一个更简单的示例,其中我将catstdin 传输到tr并将其通过管道传输到tee.

$ cat | tr a x | tee x.log

如果我输入A B Enter,然后输入Ctrl+ C,管道会在打印到标准输出或写入之前中止x.log(尽管文件本身已创建):

ab
^C

$ cat x.log

如果我输入Ctrl+D而不是Ctrl+ C,则一个EOF字符表示输入结束,并且输出将打印到 stdout 并写入x.log

ab
xb

$ cat x.log
xb

我尝试了几种不同的方法,但到目前为止没有成功。

$ { xinput test 14 | awk '{ print $NF }' ; } > >(tee x.log)

$ exec {fd}> >(tee x.log)
$ xinput test 14 | awk '{ print $NF }' >& ${fd}
$ exec {fd}>&-

$ exec > >(tee x.log)
$ xinput test 14 | awk '{ print $NF }'

这可以做到吗?

答案1

我找到了两个解决方案。

  1. 用于在没有输出缓冲的情况下stdbuf运行。awk

    xinput test 14 | stdbuf -o0 awk '{ print $NF }' | tee b.log

  2. 在脚本中添加system("")调用awk

    xinput test 14 | awk '{ print $NF; system("") }' | tee b.log

相关内容