5

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

5
  • 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, 2014 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, 2014 at 9:48
  • 2
    @Bernhard Try: od -c < test.log Apr 3, 2014 at 10:02
  • @Scrutinizer Clear, my text-editor also shows ^H
    – Bernhard
    Apr 3, 2014 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, 2014 at 11:11

2 Answers 2

12

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 (), 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).

1
  • 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, 2014 at 11:12
5

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 )

7
  • This not interpreting backspaces - this is removing them via regex.
    – mikeserv
    Apr 3, 2014 at 10:28
  • @mikeserv . Indeed, I hopefully clarified it by redirecting the examples to an output file.. Apr 3, 2014 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, 2014 at 11:42
  • 2
    Note that it turns ab\b into a instead of ab. Apr 3, 2014 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, 2014 at 12:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .