# Interpret backspaces in file

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...

-
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
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
@Bernhard Try: od -c < test.log – Scrutinizer 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 0000002$ printf 'aaa\b\b\bbb\n' | col -b | od -tc
0000000   b   b   a  \n
0000004


The sed equivalent would be something like:

bs=$(printf '\b') sed "s/^[^$bs]*/&\
\
/;:1
s/\n.\{0,1\}$$.*\n$$$$[^bs]$$/\2\
\1/;s/$$.\{0,1\}$$\n$$.*\n$$$bs/\ \1\2/;t1 s/\n//g"  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 (x̲), and x\b- or -\bx for strike-through (x̶). 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).

-
+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" – Scrutinizer Apr 3 '14 at 11:12
+1, great, never saw the usage cases for "col" before. – Olivier Dulac Apr 3 '14 at 13:27

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.. – Scrutinizer 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
Note that it turns ab\b into a instead of ab. – Stéphane Chazelas Apr 3 '14 at 11:48
col -b turns it into ab. \b doesn't delete, it moves the cursor backward. aa\b\bb should become ba. – Stéphane Chazelas Apr 3 '14 at 12:05