Compare as colunas entre arquivos diferentes

0

Eu tenho vários arquivos (cerca de 20 arquivos com 30000 linhas e 32 colunas) e preciso manter apenas as linhas que começam com a mesma string. Eu encontrei estes casos que são bastante semelhantes ao que eu preciso, mas eu não sei como adaptá-los ..

compare vários arquivos (mais de dois) com duas colunas diferentes

como comparar valores em duas colunas em dois arquivos diferentes, ecoando linhas inteiras onde o valor absoluto da diferença é < um pequeno valor máximo?

No meu caso, cada arquivo tem uma primeira coluna feita de strings de 12 caracteres, eu preciso manter apenas as linhas que começam com strings que estão presentes em todos os arquivos. (um arquivo para cada arquivo de entrada ou também um único arquivo de saída como o dos casos acima mencionados é bom). Meus arquivos são assim:

file1 :

 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -4   0 2227.39 124.894   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

file2 :

 -13  -5   0 2.19085 50.4632   1
 -13  -4  -2 283.628 56.7731   1
 -13  -4  -1  41.179 48.6423   1
 -13  -4   0 1753.54  125.88   1
 -13  -3  -3 28.2363 40.6518   1
 -13  -3  -2 562.736 66.0301   1
 -13  -3  -1 750.747 77.2795   1

Saída file1 :

 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

Saída arquivo2

 -13  -5   0 2.19085 50.4632   1
 -13  -4  -2 283.628 56.7731   1
 -13  -4  -1  41.179 48.6423   1
 -13  -3  -3 28.2363 40.6518   1
 -13  -3  -2 562.736 66.0301   1
    
por Eleonora 25.09.2015 / 16:52

1 resposta

2

Uma abordagem seria encontrar primeiro todos os conjuntos de 12 caracteres iniciais presentes em mais de um arquivo:

cut -c-12 file* | sort | uniq -c

O comando cut acima imprime os primeiros 12 caracteres de cada arquivo cujo nome começa com file , eles são classificados e o número de vezes que cada linha é encontrada é anexado por uniq -c . Executando isso nos seus arquivos de exemplo retorna:

$ cut -c-12 file* | sort | uniq -c
      1  -13  -3  -1
      2  -13  -3  -2
      2  -13  -3  -3
      2  -13  -4   0
      2  -13  -4  -1
      2  -13  -4  -2
      2  -13  -5   0

Assim, todas as linhas, exceto a primeira, aparecem nos dois arquivos. Agora, mantenha apenas as linhas que aparecem no número de vezes desejado (20 no seu caso):

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev

rev simplesmente imprime sua entrada invertida. Eu estou usando aqui para fazer o número de vezes que cada linha foi vista no último campo. Isso é então passado para sed , que é dito para imprimir apenas as linhas que terminam com um espaço, 20 e 0 ou mais espaços. Isso mantém apenas as linhas que apareceram 20 vezes e a% final rev nos traz de volta ao formato original.

Agora você pode passar a coisa toda para grep como uma lista de strings para pesquisar:

$ grep -f <(cut -c-12 file* | sort | uniq -c | 
            rev | sed -n 's/ 20 *$//p' | rev) file*
 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -4   0 2227.39 124.894   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

Se o seu shell não suportar o formato <() , você poderá salvar os resultados de cut em um arquivo separado e usá-lo, ou apenas executá-lo em um loop:

cut -c-12 file* | sort | uniq -d | 
    while IFS= read -r l; do grep -- "^$l" file1; done

Para ter a saída de cada arquivo em um arquivo separado, use:

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev > list
for f in file*; do grep -f list "$f" > "$f.new"; done
    
por 25.09.2015 / 17:28