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):
sedoperates by performing the following cycle on each lines of input: first,sedreads 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,0x0dcharacter) no final ($), execute o bloco{}, que é:- substitua
\rno final sem nada, - acrescente uma linha adicional da entrada (
N), - substitua
\nque separa a linha adicional dos dados anteriores.
- substitua
- Se o resultado contiver
\rno final (o que significa que a linha adicional o trouxe, por isso precisamos adicionar outra linha), salte parastart.