Como detectar e remover o caractere de nova linha dentro de uma coluna em um arquivo csv?

1

Eu tenho um arquivo grande (2 milhões de linhas) csv exportado de um banco de dados SQL Server . Eu não tenho acesso ao banco de dados e há algum caractere de nova linha em uma coluna, o que dificulta o processamento em R .

Exemplos de dados como este:

playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0
,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060
,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9

Nos dados de amostra acima, algumas linhas são divididas em duas linhas. Como limpá-lo?

Atualizar

  1. O arquivo csv foi gerado na plataforma Microsoft. Então, o final da linha é ^m . Eu criei os dados de amostra no Linux - terminou em \n . É meu mal, não deixei claro. Mas eu acho que posso substituir \n por \r\n .
  2. A quebra de linha nem sempre aparece antes de uma vírgula, aparece aleatoriamente mesmo dentro de um campo como

.

Bill 
Gates.

Resolvido

Etapa 1: remova ^M no meio da linha:

perl -pe 's/\r(?!\n)//g'

Ref: link

Passo 2: Substitua \n, por , (Veja a resposta de @jimmij abaixo.)

perl -p00e 's/\n,/,/g' 
    
por Nick 09.08.2015 / 02:37

2 respostas

1

perl para o resgate:

$ perl -p00e 's/\n,/,/g' file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9

Eu assumi aqui que a divisão é sempre antes de comma , .

    
por 09.08.2015 / 02:44
2

Vamos considerar isso como o arquivo de teste:

$ cat file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0
,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060
,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9
Bill
Gates,1933,0,ALS193307060,NYA,AL,1,9

Isso reúne as linhas novamente:

$ awk 'NR==1{printf "%s",$0; gsub(/[^,]/,""); nlast=n=length($0); next;} nlast==n{printf "\n";nlast=0} {printf "%s",$0; gsub(/[^,]/,""); nlast+=length($0)} END{print ""}' file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9
BillGates,1933,0,ALS193307060,NYA,AL,1,9

Os requisitos de fim de linha não são claros para mim. Poderíamos adicionar código para lidar com isso aqui. Ou, para maior flexibilidade, você pode executar o arquivo por meio de dos2unix ou unix2dos conforme necessário.

Responda pela primeira versão da pergunta

I have a large (2 Million rows) csv file

Esta é uma solução orientada a linhas que não requer a leitura de todo o arquivo na memória de uma só vez:

$ awk 'NR>1 && !/^,/{printf "\n";} {printf "%s",$0} END{print ""}' file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9

Como funciona

  • NR>1 && !/^,/{printf "\n";}

    Se não estivermos na primeira linha, NR>1 e a linha atual não começar com uma vírgula, !/^,/ , imprima uma nova linha.

  • {printf "%s",$0}

    Imprima a linha atual sem uma nova linha.

  • END{print ""}

    Quando chegarmos ao final do arquivo, imprima mais uma nova linha para finalizar a última linha.

por 09.08.2015 / 03:21

Tags