Удаление повторяющихся строк без сортировки
У меня есть утилита script в Python:
#!/usr/bin/env python
import sys
unique_lines = []
duplicate_lines = []
for line in sys.stdin:
if line in unique_lines:
duplicate_lines.append(line)
else:
unique_lines.append(line)
sys.stdout.write(line)
# optionally do something with duplicate_lines
Эта простая функциональность (uniq без необходимости сортировки первого, стабильного порядка) должна быть доступна как простая утилита UNIX, не так ли? Может быть, комбинация фильтров в трубе?
Причина для запроса: нужна эта функция в системе, на которой я не могу выполнить python извне
Ответы
Ответ 1
Блог UNIX Bash Scripting предлагает:
awk '!x[$0]++'
Эта команда сообщает awk, какие строки печатать. Переменная $0
содержит все содержимое строки, а квадратные скобки - это доступ к массиву. Таким образом, для каждой строки файла узел массива x
увеличивается и строка выводится, если ранее содержимое этого узла не было (!
).
Ответ 2
Поздний ответ - я просто столкнулся с дубликатом этого, но, возможно, стоит добавить...
Принцип ответа @1_CR может быть написан более сжато, используя cat -n
вместо awk
для добавления номеров строк:
cat -n file_name | sort -uk2 | sort -nk1 | cut -f2-
- Используйте
cat -n
для добавления номеров строк
- Использовать
sort -u
удалить повторяющиеся данные
- Используйте
sort -n
для сортировки по добавленному номеру
- Используйте
cut
для удаления нумерации строк
Ответ 3
Решение Майкла Хоффмана выше короткое и сладкое. Для более крупных файлов подход преобразования Шварца, включающий добавление поля индекса с использованием awk, сопровождаемого несколькими раундами сортировки и uniq, требует меньшего объема служебных данных. Следующий фрагмент работает в bash
awk '{print(NR"\t"$0)}' file_name | sort -t$'\t' -k2,2 | uniq --skip-fields 1 | sort -k1,1 -t$'\t' | cut -f2 -d$'\t'
Ответ 4
Спасибо 1_CR! Мне нужно было "uniq -u" (удалить дубликаты целиком), а не uniq (оставить 1 копию дубликатов). Решения awk и perl действительно не могут быть изменены, чтобы сделать это, ваши возможности! Возможно, мне также понадобилось более низкое использование памяти, так как я буду uniq'ing, как 100 000 000 строк 8-). На всякий случай, если кому-то это понадобится, я просто поставлю "-u" в команде uniq команды:
awk '{print(NR"\t"$0)}' file_name | sort -t$'\t' -k2,2 | uniq -u --skip-fields 1 | sort -k1,1 -t$'\t' | cut -f2 -d$'\t'
Ответ 5
Чтобы удалить дубликат из 2 файлов:
awk '!a[$0]++' file1.csv file2.csv
Ответ 6
Я просто хотел удалить все дубликаты по следующим строкам, а не везде в файле. Поэтому я использовал:
awk '{
if ($0 != PREVLINE) print $0;
PREVLINE=$0;
}'
Ответ 7
команда uniq
работает в псевдониме даже http://man7.org/linux/man-pages/man1/uniq.1.html
Ответ 8
Теперь вы можете проверить этот небольшой инструмент, написанный на Rust: uq.
Он выполняет фильтрацию уникальности без необходимости сначала сортировать вход, поэтому может применяться к непрерывному потоку.