Par exemple ... si j'avais un fichier comme celui-ci:

A   16  chr11   36595888
A   0   chr1    155517200
B   16  chr1    43227072
C   0   chr20   55648508
D   0   chr2    52375454
D   16  chr2    73574214
D   0   chr3    93549403
E   16  chr3    3315671

J'ai besoin d'imprimer uniquement les lignes qui ont une première colonne unique:

B   16  chr1    43227072
C   0   chr20   55648508
E   16  chr3    3315671

C'est similaire à awk '!_[$1]++', mais je veux supprimer toutes les lignes qui ont un champ de poing non unique.

Solutions Bash et Python de préférence.

1
Geparada 29 sept. 2011 à 23:06

6 réponses

Meilleure réponse

En bash, en supposant que la première colonne s'est corrigée avec (3):

sort input-file.txt | uniq -u -w 3

L'option '-u' imprime uniquement les lignes uniques et '-w 3' ne compare pas plus que les 3 premiers caractères.

7
varunl 30 sept. 2011 à 00:19
awk '
  {count[$1]++; line[$1]=$0}
  END {for (val in count) if (count[val]==1) print line[val]}
' filename

Cela peut modifier l'ordre des lignes. Si c'est un problème, essayez cette approche en 2 passes:

awk '
  NR==FNR {count[$1]++; next}
  count[$1] == 1 {print}
' filename filename
1
glenn jackman 29 sept. 2011 à 19:11

Que dis-tu de ça:

#!/usr/bin/env python
from collections import defaultdict
data = defaultdict(list)
with open('file', 'rb') as f:
    for line in sorted(f.readlines()):
        data[line[0]].append(line)
for key in sorted(data.iterkeys()):
    if len(data[key]) == 1:
        print data[key]
3
Spencer Rathbun 29 sept. 2011 à 19:18
import sys
from collections import OrderedDict
lines = OrderedDict()
for line in sys.stdin:
    field0 = line.strip().split('\t')[0]
    lines[field0] = None if field0 in lines else line
for line in lines.values():
    if line is not None:
        sys.stdout.write(line)

Si vous ne vous souciez pas de préserver l'ordre, vous pouvez utiliser un vieux dict ({}) au lieu de OrderedDict.

Cette implémentation ne se soucie pas si les champs en double sont adjacents.

0
Laurence Gonsalves 29 sept. 2011 à 19:22

Solution sed one liner:

sed ':a;$bb;N;/^\(.\).*\n\1[^\n]*$/ba;:b;s/^\(.\).*\n\1[^\n]*\n*//;ta;/./P;D' file
1
potong 31 juil. 2012 à 21:11

En python, beaucoup plus facile à lire et à modifier:

d = dict()
for line in open('input-file.txt', 'r'):
  key = line.split(' ', 1)[0]
  d.setdefault(key, list()).append(line.rstrip())

for k, v in sorted(d.items()):
  if len(v) == 1:
     print v[0]
0
theamk 29 sept. 2011 à 19:21