我编写了一个 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)
编辑:完善答案以更好地匹配问题。