4

I've written a Java-console application that repeatedly prints its status to the console using carriage-returns (\r) at the end rather than line-feeds (\n) to keep the output on one screen. I also want to pipe that output to a file, like

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

However, it doesn't make sense to write everything to that file, just what's visible at the end of the application. In other words I don't need all the "lines" ending with \r there.

Example: I code

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

"hello" appears on the screen and after two seconds it's replaced by "world". Therefore, after the program ends the user only sees "world" on the screen. Fine, that's correct.

However, if I tee that to a file it holds "hello\rworld\n", but I only want it to contain "world\n".

How do I do that on the command line rather than coding that in Java (which is why the question is here and not on SO)?

sjngm
  • 2,143

2 Answers2

5

Using sed

By default, sed reads newline-separated input. This command will remove everything before the last \r on a line:

sed 's/.*\r//'

For example:

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

To use this with tee, we can use process substitution:

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

Under bash, the construct >(...) is called process substitution. It runs the commands in the parens and puts them in a file-like object. tee write to the file-like object and the commands process the input.

Using awk

Similarly, this removes everything before the last \r on a newline-separated line:

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

The option -F'\r' sets the field separator to a carriage return. Consequently, we only want to print the last field, $NF, on each newline-separated line. Thus, print $NF.

For example:

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

To use this with tee:

echo $'line1\n\hi\rhello\rworld' | tee >(awk -F'\r' '{print $NF}' >Outfile)
John1024
  • 17,343
2

I was able to solve similar issue with col (filter reverse line feeds from input).

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

EDIT: Refined answer to better match the question.

Jaakko
  • 340