让 Tee 更好地处理运输和退货

让 Tee 更好地处理运输和退货

我编写了一个 Java 控制台应用程序,它使用末尾的回车符 (\r) 而不是换行符 (\n) 反复将其状态打印到控制台,以将输出保持在一个屏幕上。我还想将该输出通过管道传输到文件,例如

java -jar my-jar.jar | tee /tmp/my-jar.log

但是,将所有内容都写入该文件是没有意义的,只需写入应用程序末尾可见的内容即可。换句话说,我不需要那里所有以 \r 结尾的“行”。

示例:我编码

System.out.print("hello\r")
Thread.sleep(2000);
System.out.println("world")

屏幕上显示“hello”,两秒后被“world”取代。因此,程序结束后,用户只会在屏幕上看到“world”。很好,没错。

但是,如果我将其发送到一个文件,它会包含“hello\rworld\n”,但我只希望它包含“world\n”。

我如何在命令行上执行此操作而不是用 Java 编写代码(这就是为什么问题出现在这里而不是在 SO 上)?

答案1

使用 sed

默认情况下,sed读取以换行符分隔的输入。此命令将删除\r行末的所有内容:

sed 's/.*\r//'

例如:

$ echo $'line1\n\hi\rhello\rworld' | sed 's/.*\r//'
line1
world

要使用它tee,我们可以使用流程替代

echo $'line1\n\hi\rhello\rworld' | tee >(sed 's/.*\r//' >Outfile)

在 bash 下,该构造>(...)被称为流程替代。它运行括号中的命令并将它们放在类似文件的对象中。 tee写入类似文件的对象,命令处理输入。

使用 awk

\r类似地,这将删除换行符分隔行的最后一行之前的所有内容:

awk -F'\r' '{print $NF}'

该选项-F'\r'将字段分隔符设置为回车符。因此,我们只想$NF在每个以换行符分隔的行上打印最后一个字段。因此,print $NF

例如:

$ echo $'line1\n\hi\rhello\rworld' | awk -F'\r' '{print $NF}'
line1
world

要使用此功能tee

echo $'line1\n\hi\rhello\rworld' | tee >(awk -F'\r' '{print $NF}' >Outfile)

答案2

我能够解决类似的问题col (过滤输入中的反向换行符)

java -jar my-jar.jar | tee >(col -pb >/tmp/my-jar.log)

编辑:完善答案以更好地匹配问题。

相关内容