6

Some programs produce output to bash in a way that the user experience like strings that changes values rather than rows printed(bash scrolls down to be able to show all the changing output). What is this phenomena called? How is it achieved in e.g a java program or a bash script. How can the output be parsed? Is it just printing new lines but using some special function?

top is one program that uses this "phenomena" of outputting data


Okey cursors are used.

Then how can i parse them in java? I tried this code but it does not print anything

public static void exeTest(String [] args) throws IOException{
        if (args.length <= 0) {
            System.out.println("empty command");
            return;
        }

       Process process = new ProcessBuilder(args).start();
       InputStream is = process.getInputStream();
       InputStreamReader isr = new InputStreamReader(is);
       BufferedReader br = new BufferedReader(isr);


       System.out.printf("Output of running %s is:", 
          Arrays.toString(args));
       String line;
       while ((line = br.readLine()) != null) {
            System.out.println(line);
       }

Thanks for all good answers, im now more familiar at this topic even thou I still cant parse a program output like the one from top in java. Ill close this question and do more research about how to parse this in java. Then I may start another more specific one about just parsing the output in java.

The D Merged
  • 680
  • 9
  • 17

4 Answers4

4

Instead of printing whole lines (as with println or printing %n), write backspace characters (\b) or bare carriage returns without linefeeds (\r) to move the cursor back in front of what you want to print over.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • (Just don't do in your IDE, it may not support it ;)) – MadProgrammer Jul 31 '13 at 04:57
  • This sounds like a hackish solution:/ is it really standard?:S instead of writing System.out.println(str) i write for str.length build string with x \b\b\b... then str and then use System.out.print to overwrite last printed line? how can this be parsed? while(line.startswith(\b)) remove first... e.g how would one build a program that parses the cpu usage from top and shows it in a swing gui(im not doing this) – The D Merged Jul 31 '13 at 05:04
  • 2
    It is a hackish solution, but that's the standard way it's done for basic command-line programs. Anything more complicated requires a terminal library like `curses`, which is almost certainly overkill. There's no standard cross-platform way to "clear" the terminal or to go back to previous lines. The output isn't practical to screen-scrape. – chrylis -cautiouslyoptimistic- Jul 31 '13 at 05:19
2

Since you have tagged the question with bash, I am presuming that you are running linux/cygwin. Hence it's likely that the terminal is ANSI compatible. In that case, you could also use ANSI escape sequences...

e.g.:

echo -e "Hello world\rHi"
# Produces "Hillo world" since the line is not cleared before printing "Hi".
echo -e "Hello world\r\e[KHi"
#produces "Hi" (prints "Hello world", goes to 1st column, clears to last column, prints "Hi")
# For more details, refer above link.

If you need to run it in loop (which is the most obvious case), make sure that either

  1. You don't put a newline after the message string, OR
  2. You revert the vertical cursor movement (due to "\n") using ANSI escape sequence - "\e[A" (or "\e[<N>A", where N=number of lines.)

NOTE:

This code given above are bash commands. Sorry, I am not much familiar with java syntax, but to my knowledge,

  1. echo would get translated to System.out.println
  2. echo without last newline would be achievable with System.out.printf
  3. & \e refers to <ESC> character (ascii = 27), can be achieved with \033 in java string.
anishsane
  • 20,270
  • 5
  • 40
  • 73
0

It's can be done in that way you say, I mean printing new lines. Imagine you have loop:

String header = "Current val:";
String buffer = "";
for(int i = 0; i < val; i++) {
    buffer = header + " " + i + "\n";
    buffer += (val - i) + "iterations left\n";
    //add other strings to buffer...
    //Clear console here
    //Print buffer
}

So output will look static with variables changing.

Other, more powerfull way, is to use goto(x, y) like functions for precision output manipulating. Java doesn't have that in standard api, but there are libraries with it. Java gotoxy(x,y) for console applications

Community
  • 1
  • 1
MGorgon
  • 2,547
  • 23
  • 41
0

curses can be used to accomplish this. Searching for 'java curses' and 'bash curses' yields good results.


Java:

http://sourceforge.net/projects/javacurses/

What's a good Java, curses-like, library for terminal applications?

What's the best way to get text user-interfaces (ncurses-like) functionality in Java?

For Bash:

https://code.google.com/p/bashsimplecurses/

Community
  • 1
  • 1
onionjake
  • 3,905
  • 27
  • 46
  • Thanks for responding, my main problem now is about parsing the cursor output of a process executed by java. when i start the process i can call, getOutputStream, but there is nothing like get cursor – The D Merged Jul 31 '13 at 05:25