Update command line output

My program (which happens to be in Perl, although I donโ€™t think this question is specific to Perl) displays status messages at one point in a program of the form Progress: x/yy , where x and yy are a number, for example: Progress: 4/38 .

I want to โ€œoverwriteโ€ the previous output when a new status message is printed, so I do not fill the screen with status messages. So far I have tried this:

 my $progressString = "Progress\t$counter / " . $total . "\n"; print $progressString; #do lots of processing, update $counter my $i = 0; while ($i < length($progressString)) { print "\b"; ++$i; } 

The backspace character will not be printed if I include a new line in $progressString . However, if I do not use a new line, the output buffer is never flushed and nothing is printed.

What is a good solution for this?

+9
perl backspace output-formatting
Feb 15 '11 at 20:41
source share
5 answers

Use autoflush with STDOUT:

 local $| = 1; # Or use IO::Handle; STDOUT->autoflush; print 'Progress: '; my $progressString; while ... { # remove prev progress print "\b" x length($progressString) if defined $progressString; # do lots of processing, update $counter $progressString = "$counter / $total"; # No more newline print $progressString; # Will print, because auto-flush is on # end of processing } print "\n"; # Don't forget the trailing newline 
+11
Feb 15 2018-11-11T00:
source share

I know that this is not quite what you asked for, but perhaps better. I ran into this problem and instead I had to work too much with Term::ProgressBar , which also looks good.

+3
Feb 16 2018-11-11T00:
source share

Let's say

 $| = 1 

somewhere at the beginning of your program to enable autorun for the output buffer.

Also consider using "\ r" to move the cursor back to the beginning of the line, instead of explicitly counting the number of spaces you need to move backward.

As you said, do not print a new line while the progress counter is running, otherwise you will print your progress on a separate line instead of overwriting the old line.

+2
Feb 15 '11 at 20:47
source share

You can also use ANSI escape codes to control the cursor directly. Or you can use Term :: ReadKey to do the same.

+1
Feb 15 2018-11-15T00:
source share

I had to do something like this today. If you don't mind retyping the whole line, you can do something like this:

 print "\n"; while (...) { print "\rProgress: $counter / $total"; # do processing work here $counter++; } print "\n"; 

The symbol "\ r" is a carriage return - it returns the cursor to the beginning of the line. Thus, everything you print overwrites the previous progress notification text.

0
Feb 15 '11 at 22:31
source share



All Articles