Como imprimo todas as linhas de um arquivo com valores duplicados em uma determinada coluna

7

Dado um arquivo como este:

1,768,12,46576457,7898
1,123,435,134,146
2,345,6756856,12312,1311
5,234,567465,12341,1341
1,3245,4356345,2442,13
9,423,2342,121,463
9,989,342,121,1212

Eu gostaria de listar todas as linhas (no terminal bash) de forma que o valor na coluna 1 apareça pelo menos duas vezes (na coluna 1). O resultado deve ser

1,768,12,46576457,7898
1,123,435,134,146
1,3245,4356345,2442,13
9,423,2342,121,463
9,989,342,121,1212
    
por Bob 15.01.2016 / 17:13

7 respostas

11

Para tentar evitar o armazenamento de todo o arquivo na memória, você pode fazer:

awk -F , '
  !count[$1]++ {save[$1] = $0; next}
  count[$1] == 2 {
    print save[$1]
    delete save[$1]
  }
  {print}'
    
por 15.01.2016 / 18:41
4

Solução de Perl:

perl -F, -ane ' $h{ $F[0] } .= $_
                }{
                $h{$_} =~ tr/\n// >= 2 and print $h{$_} for keys %h
              ' < input-file
  • -n lê a linha de entrada por linha
  • -a divide cada linha em -F , ou seja, vírgula, na matriz @F .
  • As linhas
  • são armazenadas no hash %h codificado pelo primeiro campo ( $F[0] ). Eles são concatenados juntos ( .= ).
  • no final do arquivo ("saudação de esquimó" }{ ), fazemos um loop pelas teclas e contamos o número de novas linhas (usando o operador tr ). Se for pelo menos 2, imprimimos as linhas armazenadas.

Você pode alimentar a saída para | sort -n se quiser que a primeira coluna seja numericamente ordenada.

Atenção: se a última linha não terminasse em uma nova linha, o grupo informaria seu tamanho - 1. Você pode chomp de cada linha e adicionar as novas linhas para corrigi-lo, ou use array de matrizes de linhas em vez de array de strings.

    
por 15.01.2016 / 17:34
1

Com o awk (GNU awk para matrizes multidimensionais)

gawk -F, '
    { line[NR] = $0; count[$1]++; found[$1][NR] = 1}
    END {
        for (id in count)
            if (count[id] > 1)
                for (nr in found[id]) 
                    print line[nr]
    }
' file

A ordem da saída pode não ser a mesma do arquivo de entrada.

    
por 15.01.2016 / 18:06
1

Outra abordagem awk para remover linhas exclusivas com base na coluna 1 (ou retornar linhas duplicadas com base na coluna 1)

awk -F, 'NR==FNR{s[$1]++;next} (s[$1]>1)' infile infile
    
por 25.08.2017 / 17:18
0
for i in $(cat given | cut -d, -f1)
do
  linect=$(grep ^"${i}," given | wc -l)
  if [ ${linect} -gt 1 ]
  then
    grep ^"${i}," given >> result
  fi
done
sort result |uniq > desiredoutput

contanto que os campos sejam delimitados por vírgula e você esteja procurando duplicatas apenas na coluna 1 e na coluna 1, isso deve funcionar.

    
por 15.01.2016 / 17:39
0

Outra variante (em que test.txt é seu arquivo de entrada):

FILE=test.txt ; for n in $(cat ${FILE} | awk -F"," '{count[$1]++} END {for (i in count) print i":"count[i]}'|grep -v ':1'|awk -F: '{print $1}');do grep ^${n} ${FILE} ;done
    
por 15.01.2016 / 18:31
0

Usando o Python 3:

#!/usr/bin/env python3
import sys
from collections import defaultdict

column_delimiter = sys.argv[1]
column = int(sys.argv[2]) - 1

records = defaultdict(list)
for l in sys.stdin:
    l = l.rstrip('\n')
    r = l.split(column_delimiter)
    records[r[column]].append(l)

for ll in records.values():
    if len(ll) > 1:
        print(*ll, sep='\n')

Uso:

python3 duplicate-columns.py COLUMN-DELIMITER COLUMN

Exemplo:

python3 duplicate-columns.py ',' 1 < data.csv
    
por 23.01.2018 / 20:16