У меня есть два файла, содержащие миллиарды имен последовательности DNA, вторым является собственное подмножество первого:
например,
1°:john mike anna paul laura ....
2°:john mike paul ...
все имена занимают одну строку.
Мой вопрос, как я мог содержать имена в первом файле, которые не находятся во втором?
благодарите u все!
Это очень просто сделать, но Ваша жизнь будет намного легче, если у Вас будет одно имя на строку вместо разделенного списка пространства. Существует много превосходных утилит для управления текстовыми файлами в Linux, это - одна из вещей, в которых все *отклоняют Excel, но большинство ожидает один объект на строку. Так, большинство моих решений запустится с изменения файлов соответственно.
Измените свои файлы, чтобы иметь одно имя на строку:
sed 's/ /\n/g' file > newfile
или, для изменения исходного файла
sed -i 's/ /\n/g' file
После того как Вы сделали это, любой из них даст Вам, что Вы хотите:
grep
$ grep -vFwf file2 file1
anna
laura
comm
или diff
$ comm -23 <(sort file1) <(sort file2)
anna
laura
$ diff file1 file2 | grep -Po '<\s+\K.*'
anna
laura
awk
$ awk '(NR==FNR){a[$1]++; next}!($1 in a){print}' file2 file1
laura
anna
Perl
$ perl -lne 'BEGIN{open(A,"file2"); while(<A>){chomp; $k{$_}++}} print unless $k{$_}' file2 file1
laura
anna
или
$ perl -lne '$k{$_}++; END{map{print unless $k{$_}>1}keys(%k)}' file2 file1
laura
anna
Если Вы действительно не хотите изменять формат своего файла (но действительно, Вы должны), можно сделать что-то как
awk '{for (i=1;i<=NF;i++){a[$i]++}}END{for(n in a){if(a[n]<2){print n}}}' file2 file1
или
perl -lane '$k{$_}++ for @F; END{map{print if $k{$_}<2} keys(%k)}' file1 file2
Если они отсортированы и разделены новыми строками, Вы могли бы использовать comm
шоу Вы строки, которые уникальны для file1:
comm -23 file1 file2
демонстрация А:
$ comm -23 <(echo -e 'john\nmike\nanna\npaul\nlaura'|sort) <(echo -e 'john\nmike\npaul'|sort)
anna
laura
Или Вы могли diff
, чтобы сделать почти такую же вещь (эти grep
, ищет удаления строки):
diff sorted-file-1 sorted-file-2 | grep -oP '(?<=< ).+'
, Если бы необходимо постараться не сортировать или Вы имеете дело с серьезными числами, я обратился бы к надлежащему языку, чтобы сделать основанные на словаре поиски. Простой пример Python:
file2 = {}
with open("file2") as f:
for line in f:
file2[line] = 0
with open("file1") as f:
for line in f:
if not line in file2:
print line
Что-либо большее, чем это и Вы могли бы хотеть посмотреть на фактическую базу данных и некоторый простой SQL. Они приспособлены для больших данных.
И опция Python: независимо, если все слова находятся в одной строке или на отдельных строках:
#!/usr/bin/env python3
import sys
f1 = sys.argv[1]; f2 = sys.argv[2]
def read(f):
with open(f) as content:
return content.read().split()
for item in [w for w in read(f1) if not w in read(f2)]:
print(item)
Скопируйте сценарий в пустой файл, сохраните его как showdiff.py
сделайте это исполняемым файлом и выполните его командой:
/path/to/showdiff.py file1 file2
anna
laura
Не вопрос, но слишком много соединенный для игнорирования:
Если необходимо перечислить различия взаимно, (не только слова в file1
это не появляется в file2
, но также и слова в file2
это не появляется в file1
), сценарий ниже должен использоваться:
#!/usr/bin/env python3
import sys
f1 = sys.argv[1]; f2 = sys.argv[2]
def read(f):
with open(f) as content:
return content.read().split()
wds1 = read(f1); wds2 = read(f2); allwords = wds1+wds2
for item in [w for w in allwords if (w in wds1, w in wds2).count(False) == 1]:
print(item)
Если Вы идете опция Python, как предложил Jacob Vlijm, стоит использовать 'набор' (для дальнейшей информации, см. https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset). В основном, после того как Вы создали два набора, можно достигнуть математики набора (объединение, пересечение, различие...)
В этом случае разность множеств точно, чего Вы требуете: новый набор со всеми элементами, которые находятся в одном наборе а не в другом.
Код от Jacob затем был бы:
#!/usr/bin/env python3
import sys
f1 = sys.argv[1]; f2 = sys.argv[2]
def read_set(f):
with open(f) as content:
return set(content.read().split())
for item in read_set(f1) - read_set(f2)]:
print(item)
Конечно, для миллиардов записей, это будет требовать времени...'