How would I overwrite the previously printed line in a Unix shell with Ruby?

Say I'd like to output the current time on a shell every second, but instead of stacking down each time string, I'd like to overwrite the previously displayed time.

up vote 57 down vote accepted

You can use the \r escape sequence at the end of the line (the next line will overwrite this line). Following your example:

require 'time'

loop do
  time = Time.now.to_s + "\r"
  print time
  $stdout.flush
  sleep 1
end
  • 1
    Hmm, i like @jsegal's solution better, so choose his answer. Remember to flush your output still. – cam Feb 10 '11 at 23:15
  • 1
    I'm divided here, because your answer is a perfectly working snippet of code of what I asked exactly: a solution in Ruby. Yes, it could be more elegant if it used jsegal's suggestion. But a) jsegal's answer is not ruby specific and b) I'd much rather accept an answer with a working snippet. So I'm going to go ahead and edit your answer to reflect jsegal's suggestion, and when/if that edit is accepted, I'll accept your answer and reward jsegal by voting him up. It's the best I can do under this system. – Steph Thirion Feb 11 '11 at 6:59
  • @Steph: Your dilemma on which answer to accept seems primarily based on the fact that jsegal's answer didn't include a code snippet. Considering Stack Overflow is not a code sharing site, that seems like a fairly arbitrary requirement. You should upvote both answers if you found them useful, and accept the one that helped you the most in finding the solution that worked for you. – Cody Gray Feb 11 '11 at 7:27
  • 1
    Thanks for looking into this @Cody. My dilemma is a little more than that, I think I made it pretty clear that this answer is what I asked for (a solution in Ruby). It also meets the S.O. official guidelines: it is the answer that helped me the most. I was stuck until I tried this snippet (turns out I was not flushing). But I believe Stack Overflow is not just about helping one person on a specific moment, it's about building together a reference for the future. Hence my edit. With this in perspective I'll try to submit the edit again. – Steph Thirion Feb 11 '11 at 20:15
  • I have to emphasize the importance of \r at the end of print (as @jsegal mentioned) otherwise it won't work. – valk Dec 24 '17 at 10:36

Use the escape sequence \r at the end of the line - it is a carriage return without a line feed.

On most unix terminals this will do what you want: the next line will overwrite the previous line.

You may want to pad the end of your lines with spaces if they are shorter than the previous lines.

Note that this is not Ruby-specific. This trick works in any language!

  • Note that if the text output is wider than the current terminal window, you will start seeing line after line of output again. – Nathan Long Mar 7 '11 at 19:53
  • 4
    To avoid problems with the current line being short than the previous one. Pad it with the method rjust/ljust e.g. "my output".ljust(80). – sunsations Mar 3 '14 at 11:33

Here is an example I just wrote up that takes an Array and outputs whitespace if needed. You can uncomment the speed variable to control the speed at runtime. Also remove the other sleep 0.2 The last part in the array must be blank to output the entire array, still working on fixing it.

#@speed = ARGV[0]

strArray = [ "First String there are also things here to backspace", "Second Stringhereare other things too ahdafadsf", "Third String", "Forth String", "Fifth String", "Sixth String", " " ]


#array = [ "/", "-", "|", "|", "-", "\\", " "]

def makeNewLine(array)
    diff = nil
    print array[0], "\r"
    for i in (1..array.count - 1)
        #sleep @speed.to_f
        sleep 0.2
        if array[i].length < array[i - 1].length
             diff = array[i - 1].length - array[i].length
        end
        print array[i]
        diff.times { print " " } if !diff.nil?
        print "\r"
        $stdout.flush

    end
end

20.times { makeNewLine(strArray) }

#20.times { makeNewLine(array)}

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.