alterando os separadores de colunas em um arquivo

6

Eu tenho um arquivo grande, que preciso processar e depois de escrever alguns scripts que parecem não funcionar corretamente, descobri que um pequeno subconjunto de linhas no arquivo é, na verdade, separado por espaço, em vez de separado por tabulação.

Question: So I'm wondering what the best way would be to change these space-separated lines to tab-separated ones?

O arquivo contém 4 entradas em cada linha, cerca de 5000 entradas no total e cerca de 150 delas são separadas por espaços e não separadas por tabulações.

    
por sdf 20.08.2013 / 15:54

3 respostas

8
tr ' ' '\t' < file 1<> file

Substituiria cada caractere de espaço por um caractere de tabulação.

Só para responder às pessoas dizendo que não é seguro:

O shell abrirá o arquivo para leitura no descritor de arquivo 0, e para leitura e gravação no descritor de arquivo 1. Se algum desses falhar, ele sairá, tr nem será executado. Se os redirecionamentos forem bem-sucedidos, tr será executado.

tr lerá o arquivo um bloco por vez, fará a transliteração e emitirá o bloco modificado sobre o não modificado.

Ao fazer isso, geralmente não será necessário alocar espaço no disco. Exceção para isso seria se o arquivo era esparso para começar, ou sistemas de arquivos que implementam copy-on-write. Portanto, erros para "não há espaço disponível" não são prováveis.

Outros erros podem ocorrer como erro de E / S se o disco abaixo estiver falhando ou se o sistema de arquivos estiver em um dispositivo de bloco que tenha sido thinly provisioned (como um instantâneo LVM), sendo ambas as condições raras e de qualquer maneira provavelmente envolver o retorno de um backup.

Em qualquer caso, após a falha da chamada do sistema write() , tr deve reportar um erro e sair. Como seu stdout está aberto no modo de leitura / gravação, ele não será truncado. Para que o arquivo seja truncado, tr teria que chamar explicitamente truncate() em sua saída padrão na saída, o que não faria sentido.

O que aconteceria, no entanto, seria que o arquivo seria parcialmente transliterado (até o ponto em que tr falhou).

O que eu descobri é que o GNU tr atualmente encontrado no Debian sid amd64 tem um bug em que os segfaults após uma falha da chamada do sistema write() e saída de lixo no stdout ( edit , agora corrigido desde a versão 2.19-1 do pacote Debian libc6 ). Isso corromperia o arquivo (mas não o truncaria).

tr ' ' '\t' < file > newfile && mv newfile file

não substitui file , a menos que o newfile tenha sido criado corretamente, mas tenha vários problemas associados a ele:

  • você precisa ter certeza de não estragar um newfile já existente (pense também em symlinks)
  • Você precisa de acesso de gravação ao diretório atual
  • você precisa de espaço de armazenamento adicional para essa cópia extra do arquivo
  • você está perdendo as permissões, a propriedade, a hora de nascimento, os atributos estendidos ... do arquivo original
  • se o arquivo original for um link simbólico, você o substituirá por um regular.

tr ' ' '\t' < file 1<> file é mais seguro que o comumente usado perl -pi -e 's/ /\t/g' porque, após uma falha de perl (como no disco cheio), você perde o arquivo original e obtém apenas o que o perl gerou até agora.

    
por 20.08.2013 / 15:59
2

Você também pode usar sed .

sed -i.bak 's/ /\t/g' filename

Isso criará um filename.bak antes de editar o arquivo.

s/ /\t/g = > Isso diz a sed para substituir um espaço com o caractere de tabulação globalmente em cada linha do arquivo.

    
por 20.08.2013 / 16:56
1

Para alterar todos os espaços em um arquivo para uma guia, use tr .

tr ' ' '\t' <input_file >output_file

Para alterar todas as seqüências de um ou mais espaços para uma única guia, use sed .

sed -e 's/  */\t/g' <input_file >output_file

Algumas implementações de sed entendem \t como uma guia, outras precisam de um caractere de tabulação literal.

Se você tiver um arquivo com colunas alinhadas que use um número variável de espaços para alinhar as colunas, poderá convertê-lo para ter colunas separadas por tabulação com unexpand .

    
por 21.08.2013 / 02:21