Se esses ^M
-s forem de fato caracteres de quebra de linha, não literal caret & Seqüências de letras M, então elas são o que chamamos de \r
, CR
ou 0x0d
(compare esta resposta minha, o começo disto ).
Seu comando
sed -e "s/^M//"
não remove \r
; nem sequer remove literal ^M
. O comando significa "pegue uma linha, procure uma letra M
que esteja no início da linha ( ^
, veja isto ), substitua-o por nada.
Observação sed
entende \r
. Ainda sed -e 's/\r//'
não é exatamente o que você precisa. Ele remove \r
, mas você também precisa remover o seguinte \n
. Você pode querer tentar sed -e 's/\r\n//'
, isso também irá falhar. O problema é que sed
é uma ferramenta de texto e trata \n
como um separador. Trecho de info sed
(ênfase minha):
sed
operates by performing the following cycle on each lines of input: first,sed
reads one line from the input stream, removes any trailing newline, and places it in the pattern space. Then commands are executed; […].
Isso significa que normalmente \n
não pertence a nenhuma string processada com s/…
(ou outro comando sed
). Por esse motivo, concatenar poucas linhas não é fácil. Ainda pode ser feito . Este é o comando que você precisa:
sed -e ': start; /\r$/{ s/\r$//; N; s/\n// }; /\r$/b start'
Explicação:
-
: start
é um rótulo. - Se a linha contiver
\r
(ou seja,^M
,0x0d
character) no final ($
), execute o bloco{}
, que é:- substitua
\r
no final sem nada, - acrescente uma linha adicional da entrada (
N
), - substitua
\n
que separa a linha adicional dos dados anteriores.
- substitua
- Se o resultado contiver
\r
no final (o que significa que a linha adicional o trouxe, por isso precisamos adicionar outra linha), salte parastart
.