#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
.
Этой реализации все равно, являются ли повторяющиеся поля смежными.