unix2dos - sed replace crlf with lf




Por que a saída da minha ferramenta é sobreposta e como faço para corrigir isso? (2)

Execute o dos2unix . Enquanto você pode manipular os finais de linha com o código que você mesmo escreveu, existem utilitários que existem no mundo Linux / Unix que já fazem isso para você.

Se em um sistema Fedora dnf install dos2unix irá colocar a ferramenta dos2unix no lugar (caso não seja instalada).

Existe um pacote deb dos2unix semelhante disponível para sistemas baseados em Debian.

Do ponto de vista da programação, a conversão é simples. Pesquise todos os caracteres em um arquivo para a sequência \r\n e substitua-o por \n .

Isso significa que existem dezenas de maneiras de converter do DOS para o Unix usando quase todas as ferramentas imagináveis. Uma maneira simples é usar o comando tr onde você simplesmente substitui \r com nada!

tr -d '\r' < infile > outfile

A intenção desta questão é fornecer uma resposta para as perguntas diárias cuja resposta é "você tem finais de linha DOS" para que possamos simplesmente fechá-las como duplicatas desta sem repetir as mesmas respostas ad nauseam .

NOTA: Esta não é uma duplicata de qualquer questão existente . A intenção desta sessão de perguntas e respostas não é apenas fornecer uma resposta "executar esta ferramenta", mas também explicar a questão de tal forma que podemos apenas apontar alguém com uma questão relacionada aqui e eles encontrarão uma explicação clara do motivo pelo qual foram apontados aqui também como a ferramenta a ser executada, resolva o problema. Passei horas lendo todas as perguntas e respostas existentes, e todas elas faltam na explicação do problema, ferramentas alternativas que podem ser usadas para resolvê-lo e / ou os prós / contras / advertências das possíveis soluções. Também alguns deles aceitaram respostas que são simplesmente perigosas e nunca devem ser usadas.

Agora, voltemos à pergunta típica que resultaria em uma referência aqui:

Eu tenho um arquivo contendo 1 linha:

what isgoingon

e quando eu imprimi-lo usando este script awk para inverter a ordem dos campos:

awk '{print $2, $1}' file

em vez de ver a saída, espero:

isgoingon what

Eu recebo o campo que deve estar no final da linha aparecer no início da linha, sobrescrevendo algum texto no início da linha:

 whatngon

ou eu recebo a saída dividida em 2 linhas:

isgoingon
 what

Qual poderia ser o problema e como corrigi-lo?


O problema é que seu arquivo de entrada usa finais de linha do DOS do CRLF vez de terminações de linha do UNIX de apenas LF e você está executando uma ferramenta UNIX nele para que o CR permaneça como parte dos dados que estão sendo operados pela ferramenta UNIX. CR é comumente denotado por \r e pode ser visto como um controle-M ( ^M ) quando você executa cat -vE no arquivo enquanto LF é \n e aparece como $ com cat -vE .

Então, o seu arquivo de entrada não foi realmente apenas:

what isgoingon

foi na verdade:

what isgoingon\r\n

como você pode ver com cat -v :

$ cat -vE file
what isgoingon^M$

e od -c :

$ od -c file
0000000   w   h   a   t       i   s   g   o   i   n   g   o   n  \r  \n
0000020

Portanto, quando você executa uma ferramenta do UNIX como awk (que trata \n como a linha que termina) no arquivo, o \n é consumido pelo ato de ler a linha, mas isso deixa os 2 campos como:

<what> <isgoingon\r>

Observe o \r no final do segundo campo. \r significa Carriage Return que é literalmente uma instrução para retornar o cursor para o início da linha, então quando você faz:

print $2, $1

awk irá imprimir isgoingon e, em seguida, irá retornar o cursor para o início da linha antes de imprimir what que é porque o what parece sobrescrever o início de isgoingon .

Para corrigir o problema, faça um destes:

dos2unix file
sed 's/\r$//' file
awk '{sub(/\r$/,"")}1' file
perl -pe 's/\r$//' file

Aparentemente dos2unix é aka frodos em algumas variantes do UNIX (por exemplo, Ubuntu).

Tenha cuidado se você decidir usar o tr -d '\r' como é frequentemente sugerido, pois isso excluirá todos os \r s do seu arquivo, não apenas aqueles no final de cada linha.

Observe que o GNU awk permitirá que você analise arquivos que possuem finais de linha do DOS simplesmente configurando o RS apropriadamente:

gawk -v RS='\r\n' '...' file

mas outros awks não permitirão isso, já que o POSIX só requer awks para suportar um único caractere RS e a maioria dos outros awks silenciosamente trunca RS='\r\n' para RS='\r' . Você pode precisar adicionar -v BINMODE=3 para o -v BINMODE=3 ver até mesmo o \r s embora como os primitivos C subjacentes irão desnudá-los em algumas plataformas, por exemplo, cygwin.

Uma coisa a observar é que os CSVs criados por ferramentas do Windows como o Excel usarão o CRLF como finais de linha, mas podem ter LF embutidos em um campo específico do CSV, por exemplo:

"field1","field2.1
field2.2","field3"

é realmente:

"field1","field2.1\nfield2.2","field3"\r\n

por isso, se você converter \r\n ns em \n ns, não poderá mais informar as alimentações de linha nos campos de alimentações de linha como terminações de linha. Se você quiser fazer isso, recomendo converter todos os feeds de linha entre campos em algo anterior. por exemplo, isso converteria todos os LFs intra-campo em guias e converteria todas as linhas que terminam CRLF s em LF s:

gawk -v RS='\r\n' '{gsub(/\n/,"\t")}1' file

Fazer o mesmo sem o GNU awk saiu como um exercício, mas com outros problemas envolve a combinação de linhas que não terminam em CR quando são lidas.





dos2unix