comparar dois arquivos baseados em uma coluna e imprimi-lo

1

Eu tenho dois grandes arquivos de 400.000 linhas. Eu quero comparar a coluna 1 do segundo arquivo com a coluna 1 do primeiro arquivo recursivamente. Se combinarem, gostaria de imprimir a linha inteira. É um arquivo classificado.

      file 1: 
          name   values
          aaa    10
          aab    acc
          aac    30
          aac    abc 

      file2:
          aaa
          aac 
          aac
          aad 

como o arquivo contém 400.000 linhas, leva tempo para ser processado.

Minha solução atual é assim

    #!/bin/ksh
   while read line
   do
   var='echo $line '
   grep "$var" file1 >> /dev/null
   if [ $? -eq 0 ]
   then
   grep "$var" file1 >> present
   else
   echo " $line missing " > missing 
   fi
   done < "file2"

Como estou usando grep aqui, o valor pode estar presente em algum lugar no arquivo1 que não seja a coluna pretendida1, não quero que isso aconteça.

Minha solução esperada:

  1. compare o segundo arquivo apenas com a coluna 1 do primeiro arquivo (mesmo se fizermos isso, levará muito tempo).
  2. O uso de um script perl com ponteiro de arquivo compara duas colunas dos arquivos. Se a cadeia corresponder, imprima-a. Senão, se a coluna 1 do primeiro arquivo for maior que a do segundo arquivo, incremente o arquivo 2 AND COMPARE. Se for VICE VERSA, incremente a coluna 1 do arquivo 1 e compare.
por user68365 03.06.2014 / 10:11

3 respostas

1

join file1 file2

Por padrão, ele usará a coluna 1 para cada arquivo e omitirá as linhas que estiverem faltando nelas, que é o que você deseja. Além disso, os arquivos precisam ser classificados, o que já é o caso.

    
por 03.06.2014 / 12:27
0

É algo parecido com o que você está procurando? Eu uso cut para dividir a lista em matrizes, cada uma contendo uma coluna. Isso pressupõe que as colunas são delimitadas por um caractere de tabulação. Você pode alterar os usos de corte do delimitador especificando a opção -d . Para dividir no sublinhado: cut -d '_' .

    #!/bin/bash

    FILE1='somefile'
    FILE2='someotherfile'

    # File 1, column 1
    f1c1=($(cut -f1 -s $FILE1))
    # File 1, column 2
    #f1c2=($(cut -f2 -s $FILE1))

    # File 2, column 1
    f2c1=($(cut -f1 -s $FILE2))
    # File 2, column 2
    #f2c2=($(cut -f2 -s $FILE2))

    # Looping through all items in file 1 column 1
    for x in "${f1c1[@]}"
    do
        # For each item in f1c1, check all items in f2c1 for a match
        for y in "${f2c1[@]}"
        do
            if [[ $x == $y ]]
            then
                # The items matched!
                echo $x
                # Breaking out of the loop (no need to check for more than one
                # match, right?)
                break
            fi
        done
    done

Espero que isso ajude ou, pelo menos, você fique mais perto de uma solução.

    
por 03.06.2014 / 12:00
0

Se o número de elementos exclusivos em file2 não for muito grande, uma solução viável pode ser a abordagem clássica de processar ambos os arquivos com awk , primeiro criando uma matriz do único elementos na coluna 1 de file2 e, em seguida, testando a coluna 1 de file1 para associação na matriz, ou seja,

awk 'FNR==NR {a[$1]++}; FNR!=NR && a[$1]' file2 file1

Uma abordagem equivalente usando arrays associativos bash 4+ pode ser algo como

#!/bin/bash

declare -A a

while read col1 _ ; do
  ((a[$col1]++))
done < file2

while IFS= read -r line; do
  # compare only with 1st column of second file
  read -r col1 _ <<< "$line"
  [[ -n "${a[$col1]}" ]] && printf "$line\n"
done < file1
    
por 03.06.2014 / 16:45