Reduzir o uso excessivo de arquivos no processamento de texto

5

Atualmente, tenho um arquivo ( Results.txt ) que tem 27k linhas. O conteúdo do arquivo é como abaixo.

45008657        |       A.      |               |       Long    |       0
49210987        |       A.      |               |       Steven  |       3262
49600694        |       A.      |               |       Steven    |       4772
467814  |       A.      |       Rafeal    |       Nadal|       4133
53111047        |       A.      |       Mike    |       Tyson  |       13484

Eu preciso remover os espaços em branco extras, que estão fazendo como abaixo.

cat Results.txt | tr -d " \t\r" > Results1.txt

O arquivo ( Results1.txt ) está perfeitamente formatado sem espaços em branco extras.

45008657|A.||Long|0
49210987|A.||Steven|3262
49600694|A.||Steven|4772
467814|A.|Rafeal|Nadal|4133
53111047|A.|Mike|Tyson|13484

Agora, preciso converter todos os alfabetos em minúsculas e anexar as colunas 2 a 4.

awk 'BEGIN { FS = "|" } ; { print $1"|"tolower($2) tolower($3) tolower($4)"|"$5 }' Results1.txt > Results2.txt

Meu arquivo Results2.txt será exibido abaixo.

45008657|a.long|0
49210987|a.steven|3262
49600694|a.steven|4772
467814|a.rafealnadal|4133
53111047|a.miketyson|13484

Existe alguma maneira que eu poderia realizar todas as etapas acima mencionadas no meu arquivo inicial ( Results.txt ) em si? Eu quero reduzir o uso excessivo de arquivos para facilitar a depuração nos estágios posteriores.

EDITAR : Eu simplesmente não quero remover os arquivos uma vez depois de criar um novo arquivo que não parece uma solução elegante para mim.

    
por Ramesh 31.03.2014 / 20:31

4 respostas

10

Com o GNU sed :

sed -i 's/\s//g;s/\(|[^|]*\)|\([^|]*\)|//;s/.*/\L&/' Results.txt
    
por 31.03.2014 / 21:39
7

Você não precisa de um arquivo temporário, de fato.

awk -F'|' '{gsub("[ \t\r]", "", $0)}{print $1,tolower($2$3$4),$5}' OFS='|' inputfile

A primeira parte da expressão faz o que você faz usando tr . A segunda parte congrega os campos 2-4 e baixa esses e os imprime com os outros dois campos.

Para sua entrada, produziria:

45008657|a.long|0
49210987|a.steven|3262
49600694|a.steven|4772
467814|a.rafealnadal|4133
53111047|a.miketyson|13484

GNU awk 4.1.0 e maior suporte à edição no local. Você pode dizer:

awk -i inplace -F'|' '{gsub("[ \t\r]", "", $0)}{print $1,tolower($2$3$4),$5}' OFS='|' inputfile
    
por 31.03.2014 / 20:37
4

Com sua tentativa original, você pode colocar todos os comandos no mesmo pipeline se usar o utilitário sponge :

cat Results.txt |
  tr -d " \t\r" |
  awk 'BEGIN { FS = "|" } ;
    { print $1"|"tolower($2) tolower($3) tolower($4)"|"$5 }' |
    sponge Results.txt

sponge armazenará seu stdin na memória até atingir o final da entrada e, em seguida, gravará no arquivo. Isso deve ser aceitável para um arquivo do tamanho mencionado.

Note que você também pode usar um redirecionamento de shell para inserir um arquivo em td em vez de cat , por exemplo:

tr -d " \t\r" <Results.txt
    
por 31.03.2014 / 20:52
2

Use apenas uma ferramenta que permita a edição em andamento. Perl por exemplo:

perl -i -F'\|' -lane 's/[ \t]+//g for @F; print lc("$F[0]|$F[1]$F[2]$F[3]|$F[4]")' a
  • O -i ativa a edição interna, as alterações são aplicadas diretamente no arquivo original (em outras palavras, perl lida com a criação e exclusão do arquivo temporário).

  • O -a ativa a divisão automática no caractere dado por -F , os campos são salvos no array @F .

  • O s/[ \t]+//g remove todos os espaços e tabulações e o lc() deixa tudo em minúsculas.

por 31.03.2014 / 21:06

Tags