Caracteres do código 0 a 31 em ASCII são caracteres de controle. Quando enviados para um terminal, costumam fazer coisas especiais. Por exemplo, \a
(BEL, 0x7) toca a campainha do terminal. \b
(BS, 0x8) move o cursor para trás. \n
(LF, 0xa) move o cursor uma linha para baixo, \t
(TAB 0x9) move o cursor para a próxima tabulação ...
\r
(CR, 0xd) move o cursor para a primeira coluna.
Quando você executa em um prompt do shell em um terminal:
printf 'foo\nbar\n'
printf
escreve foo\nbar\n
para /dev/tty<something>
, a disciplina de linha tty desse dispositivo traduz isso para foo\r\nbar\r\n
, e é por isso que você vê bar
na próxima linha depois de foo
.
printf 'foo\rbar\n'
O terminal teria que sobrescrever foo
com bar
.
Se o seu arquivo contiver caracteres de controle, você poderá removê-los ou dar a eles uma representação textual (por exemplo ^M
ou \r
para o caractere CR 0xd) se você quiser verificar a presença deles.
Você pode não querer fazer isso para os caracteres LF e TAB. Então:
LC_ALL=C tr -d 'LC_ALL=C sed "$(printf 's/[^\t -60-7]/^&/g')" < file |
LC_ALL=C tr 'printf 'foo\nbar\n'
--7' '@-HK-_?'
--7' < file # to remove them
cat -v < file # to display as ^M
sed -n l < file # to display as \r (also converts TAB to \t)
# and marks the end of lines with $
Observe que os sed
e cat
também transformariam caracteres não ASCII. Você poderia fazer em vez disso:
printf 'foo\rbar\n'
Para converter somente os caracteres de controle ASCII (exceto TAB e LF) para sua forma visual ^X
(note que nem todas as implementações de sed
suportam arquivos de entrada com caracteres NUL).