Como contar os delimitadores e remover os Feeds de linha se não atenderem ao limite

0

Tenho vários arquivos com até um milhão de registros provenientes de um fornecedor.

Esses arquivos são originalmente de um ambiente Windows e, quando os obtemos, eles têm divisões errôneas nos registros causados por alimentações de linha no meio de campos de texto.

Acho que isso é causado por caracteres que são interpretados como Line Feeds durante a transferência para o Linux, mas não tenho certeza, pois nunca vemos os arquivos originais do Windows.

O que preciso é de uma rotina que conte o número de delimitadores em uma linha e, se estiver abaixo de um limite especificado, exclua o feed de linha no final do registro. Então, por exemplo, sabemos que um registro é 29 colunas e deve ter 28 delimitadores "pipe" ("|") quando recebemos os dados por causa do Line Feed errôneo recebemos dois registros, um com, por exemplo, 10 campos e 9 delimitadores e um segundo com 19 campos e 18 delimitadores. Aqui está um exemplo com os dados alterados para segurança:

9999999999|Duck Donald|87|||999999999|9999999999|XX999999|||Z99999|999 Planet Ln|||Trumpet
ville|ZZ|99999||||||ZZ|P|9999999999|F|||

Observe que a linha se divide na palavra Trumpetville. Isso ocorre porque o caractere de feed de linha foi inserido ou traduzido incorretamente. Novamente, procure por um woutine para contar os delimitadores e remover o Feed de linha se o número de delimitadores estiver abaixo do limite especificado.

    
por powerski 10.01.2017 / 14:38

3 respostas

1

Tente:

sed -e :1 -e 's/|/|/28;t' -e 'N;s/\n//;t1' < your-file

Ou:

awk -F'|' '{while (NF < 29 && (getline nextline) > 0)
   $0 = $0 nextline; print}' < your-file

Caso o texto contenha delimitadores de linha CRLF Microsoft, talvez você queira primeiro processar os arquivos com dos2unix.

    
por 10.01.2017 / 16:11
0

Assumindo que o CRLF indesejado nos dados não ocorre no início do campo, você poderia:

Substitua o CRLF pretendido no final da linha com o EOL do linux, o LF .

Isso deve ocorrer após um caractere de pipe. Éter diretamente ou separado por um espaço. Então, substitua a (s) string (s) “space pipe CRLF” e “pipe CRLF” por “pipe space LF” ou “pipe LF”

0x7C 0x20 0x0D 0x0A e 0x7C 0x0D 0x0A

para

0x7C 0x20 0x0A e 0x7C 0x0A

Agora, o único CRLF que permanece está nos dados. Substitua a string "CRLF" por um espaço ou nulo.

0x0D 0x0A a 0x20

editar:

O EOL pretendido deve estar entre 2 tubos.

| dados | CRLF

| dados |

0x7C 0x0D 0x0A 0x7C
    
por 10.01.2017 / 15:39
0

script bash

Eu li que a resposta original não é exatamente o que você está procurando. Por favor, veja o seguinte roteiro. Isso só funciona quando você está ciente da quantidade de elementos do arquivo de entrada de antemão:

#!/bin/bash

infile=/home/wokie/duck.txt
outfile=/home/wokie/duck2.txt
# Define the amount of elements/columns in a row
maxelem=28

# Read the file, strip all newline characters and create one big variable
inputOneline=$(cat $infile | dos2unix | tr -d '\n')

count=0
# Read through the variable and split elements
for element in ${inputOneline//|/ }
  do
  if [ $count -lt $maxelem ]
    then
      # Write element to outfile while suppresing newline (-n) 
      echo -n "$element|" >> $outfile
      count=$[$count +1]
    else
      # Write newline to outfile when maximum elements is reached
      echo >> $outfile
      count=0
  fi
done

A ideia é tirar todas as novas linhas, depois disso um novo arquivo é colocado junto com as novas linhas nos lugares certos.

dos2unix

O script faz uso de uma ótima ferramenta chamada dos2unix. Ao executar o dos2unix apenas com o nome do arquivo como parâmetro, ele converterá automaticamente o arquivo de entrada (Windows) para o formato unix.

Se você iniciar a ferramenta com o parâmetro -id, o número de ocorrências de CRLF será contado, por exemplo:

[test@testsystem ~]$ dos2unix -id /home/wokie/test2.txt 5 /home/wokie/test2.txt

No arquivo de exemplo, existem 5 ocorrências.

Você pode encontrar a ferramenta dos2unix aqui: link . A maioria das distros fornece o dos2unix como padrão ou oferece a possibilidade de instalação usando o apt-get ou o dnf.

    
por 10.01.2017 / 15:54