Как печатать только строки с уникальными полями?

#python #bash #unique

#python #bash #уникальный

Вопрос:

Например … если бы у меня был такой файл:

 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
  

Мне нужно печатать только те строки, которые имеют уникальный первый столбец:

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

Это похоже на awk '!_[$1] ' , но я хочу удалить все строки, которые имеют неуникальное первое поле.

Предпочтительно решения на Bash и python.

Комментарии:

1. Всегда ли он сортируется по первому столбцу?

2. У вас есть фиксированный диапазон значений для первого столбца? И если да, то каков диапазон?

Ответ №1:

в bash, предполагая, что первый столбец исправлен с помощью (3):

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

Опция ‘-u’ печатает только уникальные строки, а ‘-w 3’ сравнивает не более первых 3 символов.

Комментарии:

1. Это действительно быстро и эффективно для памяти, но я не упомянул, что реальные данные имеют переменное количество символов… но я мог бы использовать awk '{print $0, "t", $1}' file |sort | uniq -u -f 4 Спасибо за вашу строку!

Ответ №2:

Как насчет этого:

 #!/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:

 awk '
  {count[$1]  ; line[$1]=$0}
  END {for (val in count) if (count[val]==1) print line[val]}
' filename
  

Это может изменить порядок строк. Если это проблема, попробуйте этот 2-проходной подход:

 awk '
  NR==FNR {count[$1]  ; next}
  count[$1] == 1 {print}
' filename filename
  

Ответ №4:

решение sed one liner:

 sed ':a;$bb;N;/^(.).*n1[^n]*$/ba;:b;s/^(.).*n1[^n]*n*//;ta;/./P;D' file
  

Ответ №5:

в python гораздо проще читать и настраивать:

 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]
  

Ответ №6:

 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)
  

Если вы не заботитесь о сохранении порядка, вы могли бы использовать простой старый dict ( {} ) вместо OrderedDict .

Этой реализации все равно, являются ли повторяющиеся поля смежными.