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