Is there a way to interpret/"execute" backspaces in a file/line using common bash commands? I have a console program which prints some stuff and than erases it using backspaces and finally writes the end result. What I actually want is the output at the end.

echo -e "Foo\b\b\bBar" | what_goes_here > test.log

My test.log should only contain "Bar". I guess a problem to do this is how much text should be buffered until considered as really printed... In my case a "line buffered" interpreter would be sufficient.

Most utility have a switch which do not print such characters in first place. But the utility at hand has no such switch...

  • 1
    I really don't know what you want to do, could you try to make it clearer ? maybe add a concrete example because is pretty confusing in my opinion
    – Kiwy
    Apr 3 '14 at 9:10
  • 2
    echo -e "Foo\b\b\bBar" > test.log works for me to have only Bar in test.log. Can you elaborate why this does not work for you?
    – Bernhard
    Apr 3 '14 at 9:48
  • 2
    @Bernhard Try: od -c < test.log Apr 3 '14 at 10:02
  • @Scrutinizer Clear, my text-editor also shows ^H
    – Bernhard
    Apr 3 '14 at 10:59
  • @Bernhard then your text editor "interprets" the backspaces for you. I want a clean text file, only Bar (check hexdump -C test.log)
    – falstaff
    Apr 3 '14 at 11:11

That's what col -b is for:

$ printf 'a\bb\n' | col -b | od -tc
0000000   b  \n

$ printf 'aaa\b\b\bbb\n' | col -b | od -tc
0000000   b   b   a  \n

The sed equivalent would be something like:

bs=$(printf '\b')
sed "s/^[^$bs]*/&\

Dating to the times of the real tele-typewriters (tty), the x\bx sequence is sometimes found to represent a bold x (x typed over itself), x\b_ or _\bx for an underlined x (), and x\b- or -\bx for strike-through ().

Another useful command to deal with those is the colcrt command.

$ printf '_\bfo\b_o\b_ bar b\b-a\b-z\b-\n' | colcrt
foo bar baz

Another option is to convert \b_ and \b- to the Unicode combining characters U+0332 and U+0336:

Here assuming a Unicode locale and zsh, ksh93 or bash:

$ printf 'f\b_o\b_o\b_ bar b\b-a\b-z\b-\n' | sed $'s/\b_/\u0332/g;s/\b-/\u0336/g'
f̲o̲o̲ bar b̶a̶z̶

(pipe to colcrt or col -b to also handle the x\bx bold).

  • 3
    +1: Had forgotten about that one :) . One would expect it to be part of POSIX, but apparently it was left out (but allowed as an "extension") on the basis that "No utilities defined in POSIX.1-2008 produce output requiring such a filter" Apr 3 '14 at 11:12

Try sed

if used in ksh93/zsh/bash

printf "Foo\b\b\bBar\n" | sed -e :a -e "s/.\{0,1\}"$'\b'"//;ta" > test.log

or more portable

printf "Foo\b\b\bBar\n" | sed -e :a -e "s/.\{0,1\}$(printf "\b")//;ta" > test.log

or GNU sed:

printf "Foo\b\b\bBar\n" | gsed -re ":a;s/.?\x08//;ta" > test.log

Note: this approach treats '\b' as a backward erase instead of a backspace, so there would be a difference if the number of characters after a number of \b is less than the number of \b. (Thanks @StephaneChazelas )

  • This not interpreting backspaces - this is removing them via regex.
    – mikeserv
    Apr 3 '14 at 10:28
  • @mikeserv . Indeed, I hopefully clarified it by redirecting the examples to an output file.. Apr 3 '14 at 10:29
  • Yeah, I tried doing it with stty, but I can't figure it out - there are too many options and it's over my head - I know it can be done I just don't know how. Anyway, this absolutely works - and I removed my downvote. But if you can figure out to read and write the tty after it's been interpreted reliably, I'll definitely upvote. Nevermind, have one anyway.
    – mikeserv
    Apr 3 '14 at 11:42
  • 2
    Note that it turns ab\b into a instead of ab. Apr 3 '14 at 11:48
  • 1
    col -b turns it into ab. \b doesn't delete, it moves the cursor backward. aa\b\bb should become ba. Apr 3 '14 at 12:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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