Interpretar backspaces no arquivo

4

Existe uma maneira de interpretar / "executar" backspaces em um arquivo / linha usando comandos bash comuns? Eu tenho um programa de console que imprime algumas coisas e que apaga usando backspaces e finalmente grava o resultado final. O que eu realmente quero é a saída no final.

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

Meu test.log deve conter apenas "Barra". Eu acho que um problema para fazer isso é quanto o texto deve ser armazenado em buffer até ser considerado realmente impresso ... No meu caso, um interpretador de "buffer de linha" seria suficiente.

A maioria dos utilitários tem um switch que não imprime tais caracteres em primeiro lugar. Mas o utilitário em mãos não tem esse tipo de mudança ...

    
por falstaff 03.04.2014 / 11:06

2 respostas

12

É para isso que col -b :

$ 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

O sed equivalente seria algo como:

bs=$(printf '\b')
sed "s/^[^$bs]*/&\
\
/;:1
s/\n.\{0,1\}\(.*\n\)\([^$bs]\)/\
/;s/\(.\{0,1\}\)\n\(.*\n\)$bs/\
/;t1
s/\n//g"

Relacionado aos tempos das tele-máquinas de escrever reais (tty), a sequência x\bx às vezes representa% arx ( x digitado em si), x\b_ ou _\bx para um sublinhou x ( ) e x\b- ou -\bx para passagem direta ( ).

Outro comando útil para lidar com isso é o comando colcrt .

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

Outra opção é converter \b_ e \b- nos caracteres combinados Unicode U + 0332 e U + 0336:

Aqui, assumindo uma localidade Unicode e zsh , ksh93 ou 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̶

(canalize para colcrt ou col -b para também processar x\bx negrito).

    
por 03.04.2014 / 12:57
5

Experimente sed

se usado em ksh93/zsh/bash

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

ou mais portátil

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

ou  GNU sed:

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

Nota: esta abordagem trata '\ b' como um apagamento retroativo em vez de um retrocesso, portanto, haveria uma diferença se o número de caracteres após um número de \ b for menor que o número de \ b. (Obrigado @StephaneChazelas)

    
por 03.04.2014 / 11:39