Removendo primeiro ^ M de cada linha do arquivo

2

Os dados começam na segunda linha. Existe um script ou utilitário simples para remover a primeira instância de ^m em cada linha de dados?

O problema também pode ser reformulado como: como cada segunda (mesmo) instância de ^m pode ser removida? Olhando para frente respostas interessantes (inteligentes). De preferência no Ubuntu ou similar.

Dadosbrutosparaosespertoscortar,colareanalisar:

Date,From,To,Flight_Number,Airline,Distance,Duration,Seat,Seat_Type,Class,Reason,Plane,Registration,Trip,Note,From_OID,To_OID,Airline_OID,Plane_OID^M--,JFK,OTBD,AmericanAirlines(AA),AmericanAirlines,6687,13:52,,,,,777^M,,,"Direct",3797,2241,24^M
- -,JFK,OTBD,Qatar Airways (QR),Qatar Airways,6687,13:52,,,,,77W^M,,,"Direct",3797,2241,4091^M

Dito isto, a razão para colocar essa questão é que o inesperado está causando problemas de importação no Libre-Office Calc (planilha eletrônica): ela causa uma nova linha esperada.

    
por gatorback 30.07.2016 / 18:06

6 respostas

8

Supondo que você queira manter o arquivo no formato DOS (finais de linha CRLF), podemos trapacear; remova all os CR's e adicione-os novamente no final da linha.

Então

tr -d '5' < srcfile | unix2dos > newfile

EDIT para descrição detalhada:

O

tr -d '5'

removerá todos dos caracteres de controle-M do arquivo. -d to tr significa "delete" e '5' é o caractere de controle-M no formato octal.

O

unix2dos

converterá qualquer caractere LF (linefeed; control-J;) em CRLF inserindo um CR (control-M) antes do caractere LF; isso converte um arquivo de texto de formato unix em um arquivo de texto no formato DOS.

Coloque os dois juntos e apagamos todos os rogue ^ M's e garantimos que os únicos estejam no final de cada linha.

    
por 30.07.2016 / 18:53
2

(Baseado no fato de que sua imagem mostra o ^M em azul, ao contrário do branco normal, eu suponho que você quer dizer o caractere de retorno de carro (CR), e não uma combinação de cursor + M literalmente. este é um caso em que postar texto como uma imagem pode realmente ser útil.))

1) Como você está alimentando os dados para o LibreOffice, você pode ver se eles lidariam bem com os feeds de linha do estilo Unix (apenas LF, em vez de CRLF) e apenas removeriam todos os retornos de carro por completo:

tr -d '\r' < input > output

2) Se você quiser manter os finais de linha CRLF estilo DOS, e apenas remover os CR: s que estão no meio da linha (ou seja, não imediatamente seguidos por LF), você poderia fazer isso em Perl:

perl -pe 's/\r(?!\n)//g' < input > output

s/xxx/yyy/g substitui todas as ocorrências de xxx por yyy , \r é interpretado como o caractere de retorno de carro e (?!\n) significa "não seguido por \n ", em que \n é a nova linha / linefeed character. A substituição está vazia, portanto, as correspondências são removidas.

Você poderia fazer algo semelhante com sed , mas a saída \r não é suportada em todas as versões de sed e inserir o caractere ctrl-M literalmente na linha de comando é um tanto irritante. (O Ubuntu teria o GNU sed, que o suporta, mas também tem o Perl, portanto).

Ignorei especificamente tudo o que você disse sobre a primeira ocorrência em cada linha e sobre ignorar a primeira linha, pois acho um pouco frágil confiar na entrada para sempre conter exatamente a quantidade correta de caracteres extras de controle espúrios. (E se alguma linha tiver dois ^M : s, ou nenhum?)

    
por 31.07.2016 / 02:45
2

Aqui está uma opção usando sed :

sed -i.bak '2,$s/\r//' filename

O que faz:

  1. -i.bak adiciona um backup do arquivo original como filename.bak .
  2. 2,$ é iniciar na segunda linha e continuar até o final do arquivo.
  3. s/\r// remove a primeira ocorrência do retorno de carro (^ M na captura de tela) em cada linha.

Exemplo de comando usando extrato publicado, onde eu inseri manualmente os retornos de carro no vi:

$ cat -A test_sed
Date,From,To,Flight_Number,Airline,Distance,Duration,Seat,Seat_Type,Class,Reason,Plane,Registration,Trip,Note,From_OID,To_OID,Airline_OID,Plane_OID^M$
- -,JFK,OTBD,American Airlines (AA),American Airlines,6687,13:52,,,,,777^M,,,"Direct",3797,2241,24^M$
- -,JFK,OTBD,Qatar Airways (QR),Qatar Airways,6687,13:52,,,,,77W^M,,,"Direct",3797,2241,4091^M$

$ sed -i.bak '2,$s/\r//' test_sed

$ cat -A test_sed
Date,From,To,Flight_Number,Airline,Distance,Duration,Seat,Seat_Type,Class,Reason,Plane,Registration,Trip,Note,From_OID,To_OID,Airline_OID,Plane_OID^M$
- -,JFK,OTBD,American Airlines (AA),American Airlines,6687,13:52,,,,,777,,,"Direct",3797,2241,24^M$
- -,JFK,OTBD,Qatar Airways (QR),Qatar Airways,6687,13:52,,,,,77W,,,"Direct",3797,2241,4091^M$
    
por 30.07.2016 / 18:31
1

Veja o que você pode fazer usando o SED nas versões GNU e BSD para remover a primeira ocorrência de algo:

sed '2,/RE/s/\^M//' yourFile

E aqui está o que você pode fazer para remover o segundo - ou nth - ocorrência:

sed '2,/RE/s/\^M//2' yourFile

# O primeiro é o mesmo que sed '2,/RE/s/\^M//1' yourFile

N.B. /RE/ interromperia a substituição se alguma linha contiver RE . Você pode preenchê-lo com qualquer outra coisa. OU você pode usar apenas sed '2,$s/\^M//' yourFile , a escolha é sua.

    
por 30.07.2016 / 19:02
1

Para responder a pergunta no assunto: remova todos os outros caracteres CR no arquivo , com GNU awk :

awk -v RS='\r' '{ORS = NR % 2 ? RT : ""; print}' < infile > outfile

Define o separador de entrada (entrada) como CR e define o separador de registro de saída como RT (o terminador de registro para este registro que pode ser CR ou nada se for o último registro e a entrada não terminar em um CR caractere) apenas para registros pares (quando NR % 2 != 0 ).

    
por 31.07.2016 / 12:48
0

Para remover os CRs não no final da linha com sed , você pode fazer:

CR=$(printf '\r')
sed -e :1 -e "s/$CR\(.\)//g;t1" < infile > outfile

Ou já que você está no Ubuntu, onde sed é GNU sed :

sed -E ':1;s/\r(.)//g;t1' < infile > outfile

Procura por CRs seguidos por um caractere (o que acontece para todos os CRs, exceto aqueles no final da linha) e os substitui por esse caractere (capturado em ). Ele faz isso repetidamente em um loop para responder por CRs consecutivos.

Agora, é somente para importar em um software Unix, você pode também remover todos CRs, então você acaba com um arquivo de texto no formato Unix (as terminações de linha CRLF são apenas para sistemas operacionais Microsoft , você tem muita sorte que o software entenda linhas terminadas CRLF em primeiro lugar):

tr -d '\r' < infile > outfile
    
por 31.07.2016 / 12:22