Как найти уникальные строки из каждого файла с учетом 3 текстовых файлов
У меня есть 3 текстовых файла с некоторыми уникальными идентификаторами, и я хочу сохранить только уникальные идентификаторы в каждом текстовом файле. Допустим, есть 3 файла (A, B и C). Если идентификатор "abc" появляется в A и B, его необходимо удалить из обоих файлов.
Файлы сортируются и имеют размер менее 1 МБ, а идентификаторы представляют собой буквенно-цифровые символы. Также внутри каждого файла нет дубликатов.
Есть ли способ сделать это, просто используя инструменты командной строки в Linux или Mac? Сначала я думал о написании кода, но сначала хотел спросить. Спасибо!
2 ответа
Предположения:
- текстовые файлы имеют один идентификатор на строку
- каждая строка содержит только идентификатор и никакой другой текст
- идентификаторы не повторяются в файле
- все в порядке, чтобы изменить порядок вывода файла (сортировать его)
- эффективность исполнения не важна
- Идентификаторы буквенно-цифровые
$ cat A B B C C | sort | uniq -u >A.uniq
$ cat B A A C C | sort | uniq -u >B.uniq
$ cat C A A B B | sort | uniq -u >C.uniq
$ mv A.uniq A
$ mv B.uniq B
$ mv C.uniq C
Команда 'cat' объединяет перечисленные файлы вместе. Первый файл, который я хочу удалить дубликаты. Следующие файлы - потенциальные дубликаты, которые я хочу удалить. Я добавляю по две копии каждого из этих файлов, чтобы гарантировать, что они дублируются и будут удалены.
Затем я сортирую эти файлы по алфавиту. Это приводит к тому, что любые дублированные идентификаторы находятся на соседних строках в отсортированном выводе.
Команда 'uniq' с опцией '-u' выводит только строки, которые являются уникальными. Если два или более одинаковых идентификатора появляются на соседних строках ввода, ничего не выводится.
">" Записывает вывод в новый файл с именем "A.uniq"
Если вы хотите сделать обратное и сгенерировать список всех идентификаторов, которые дублируются в 3 файлах, вы можете сделать что-то вроде:
$ cat A B C | sort | uniq -d >duplicates
Команда 'uniq' с флагом '-d' выводит строку только в том случае, если она повторяется на входе два или более раз.
Спасибо за отвлечение - я придумал следующий сценарий (задокументировано) -
#! /bin/bash
SOURCEFILES="./existing/list1.txt ./existing/list2.txt ./existing/list3.txt"
# First find a list of duplicate files. We do this by catting all files and finding where there are lines that are not unique
# $DUPLICATES will be a space seperated list of duplicate IDs
DUPLICATES=$( cat $SOURCEFILES | sort | uniq -d )
echo "Duplicates Found for removal: " $DUPLICATES
# Convert list of duplicates into a pipe seperated list
# Commented out version assumes all ID's are all the same length, so it would break if one is ABC and another is ABCD
#DUPLICATES=$( echo $DUPLICATES | tr ' ' '|' )
# This version translates the duplicate REGEX to say that each line is complete
# ^ means start of line and $ means end of line.
for each in $DUPLICATES
do
DUPLIST="$DUPLIST^$each$|"
done
# Remove trailing "|" from DUPLIST
DUPLICATES=$( echo ${DUPLIST::-1} )
# Go through each file, removing duplicates
for each in $SOURCEFILES
do
mv $each $each.old
egrep -v "$DUPLICATES" < $each.old > $each
done