12

I wonder why backspace character in common Linux terminals does not actually erase the characters, when printed (which normally works when typed)..

This works as expected:

$ echo -e "abc\b\b\bxyz"
xyz

(\b evaluates to backspace, can be inserted also as Ctrl+V Ctrl+H - rendered as ^H (0x08))

but when there are less characters after the backspaces, the strange behavior is revealed:

$ echo -e "abc\b\b\bx"
xbc

it behaves like left arrow keys instead of backspace:

$ echo -e "abc\e[D\e[D\e[Dx"
xbc

erase line back works normally:

$ echo -e "abc\e[1Kx"
x

In fact, when I type Ctrl+V Backspace in terminal, ^? (0x7f) is yielded instead of ^H, this is Del ascii character, but Ctrl+V Del produces <ESC>[3~, but it is another story..

So can someone explain why printed backspace character does not erase the characters?

(My environment is xterm Linux and some other terminal emulators, $TERM == xterm, tried vt100, Linux as well)

mykhal
  • 19,175
  • 11
  • 72
  • 80

1 Answers1

23

What you are seeing is correct. Backspace or ^H moves the cursor to the left, no erasing. To erase a character, you need to output ^H ^H (Backspace-Space-Backspace).


To answer your comment - Backspace is defined that way in the VT100/ANSI family of terminals, from which a lot of terminal control code sequences borrow. See the VT100 user manual here which defines the function of BS as "Moves cursor to the left one character position, unless it is at the left margin, in which case no action occurs". In other words it's a quirk of history :)

As to why it was defined this way initially - I guess it's more flexible to have a non destructive cursor movement control code, as destructive backspace can be implemented as shown above.

clstrfsck
  • 14,715
  • 4
  • 44
  • 59
  • well, this is not an explanation _why_ backspace control character behaves like left cursor key, not according to commons sense (erase last character) – mykhal May 18 '10 at 10:51
  • 15
    The REAL reason it works this way is because of even older, "hard copy" terminals that print on paper like a typewriter. On such a terminal there's NO way to erase a character once it's been output. Typewriter-like terminals are also the reason we're still stuck with separate "carriage return" and "line feed" characters to end lines on Windows. – alexis Mar 12 '12 at 13:24
  • 3
    Incidentally, I don't know about common sense but "backspace" means "move backwards", not "erase". I don't care either way but Richard Stallman was quite vocal about how wrong your take is and how Delete is the true erase. He refused to free up the ^H key in emacs since he was not interested in "catering to broken protocols", or some such. :-) – alexis Mar 12 '12 at 13:28
  • 3
    Also `F^HF` is bold, this output is produce by `man` and `less` handle it, try `echo -e F^HFO^HOO^HO | less`. Now I understand why, it's simple print the same character twice in the same place. – jcubic Sep 22 '12 at 21:04
  • @jcubic's code didn't quite work for me. For those who want to play around with this try `echo -e 'F\bFO\bOO\bO' | less` – jpyams Sep 21 '17 at 14:27
  • @jpyams I don't remember but I think that `^H` is just representation of `\b` not literal two characters. I think that I show it that way because that's how it was presented in the answer. – jcubic Sep 21 '17 at 18:20
  • @jcubic that makes sense. I posted the command that worked for me just for anyone who might want to play with what you're talking about in the future – jpyams Sep 24 '17 at 01:03