Печать уникальных линий

15

Есть ли лучшее решение для печати уникальных линий, кроме комбинации sortи uniq?

Позволь мне быть
источник
1
Что вы подразумеваете под «лучше»?
таращиться
@gabe Например, не требуется хранить весь файл в памяти.
Let_Me_Be
Некоторые версии sort(например, GNU coreutils) используют временные файлы и внешнюю сортировку слиянием, если ввод слишком велик для размещения в ОЗУ. И большинство других версий имеют -mопцию, так что это можно сделать явно, разбив входные данные (например, с помощью split), отсортировав каждый чанк, а затем объединив чанки
jhnc

Ответы:

25

Чтобы напечатать каждую одинаковую строку только одну, в любом порядке:

sort -u

Для печати только уникальных строк в любом порядке:

sort | uniq -u

Чтобы напечатать каждую одинаковую строку только один раз, в порядке их первого появления: (для каждой строки выведите строку, если она еще не была видна, затем в любом случае увеличьте счетчик видимых значений)

awk '!seen[$0] {print}
     {++seen[$0]}'

Чтобы напечатать только уникальные строки, в порядке их первого вхождения: (запишите каждую строку seen, а также, linesесли это первое вхождение; в конце ввода напечатайте строки в порядке вхождения, но только те, которые видны только один раз)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'
Жиль "ТАК - прекрати быть злым"
источник
8
как насчет awk '!seen[$0]++ {print}'?
Asoundmove
10
Или даже короче awk '!seen[$0]++', поскольку {print}подразумевается пустой командой.
Quazgar
3

Некоторые (большинство?) Версии sortимеют -uфлаг, который выполняет uniqроль напрямую. Могут быть некоторые ограничения длины строки, в зависимости от реализации, но у вас уже были те, которые были с plain sort|uniq.

Мат
источник
1
Э - э? sort -uвосходит к V7 по крайней мере.
geekosaur
Хм ... Я думал, что вспомнил, что у Solaris или AIX такого не было. Я ошибаюсь, у них обоих это есть.
Мат
Solaris и AIX имеют -uограничение длины строки в 512 символов. (На самом деле, я думаю, что где-то около Solaris 9 Sun повысил его до 5120. Хотя GNU все еще выигрывает.)
geekosaur
@geekosaur: ты уверен? Работа, проделанная для снятия 512-байтового ограничения на длину строки в виде, была задокументирована в «Теории и практике при построении процедуры рабочей сортировки» JP Linderman, Bell System Technical. Журнал, 63, 1827-1843 (1984).
Джонатан Леффлер
0

Perl работает на тебя? Он может сохранять строки в исходном порядке, даже если дубликаты не являются соседними. Вы также можете написать код на Python или awk.

while (<>) {
    print if $lines{$_}++ == 0;
}

Который может быть сокращен до просто

perl -ne 'print unless $lines{$_}++;'

Данный входной файл:

abc
def
abc
ghi
abc
def
abc
ghi
jkl

Это дает результат:

abc
def
ghi
jkl
Джонатан Леффлер
источник
Где определяются $ строки?
Грегг Левенталь
Это не так. Так как здесь нет use strict;или use warnings;(на самом деле, это strictнаиболее актуально здесь), нет никаких претензий к использованию %linesдо того, как оно будет определено. Если запустить со стриктурами, my %lines;перед циклом должна быть линия . Обратите внимание, что хеш есть %lines; на один элемент хеша ссылаются с использованием $lines{$_}нотации.
Джонатан Леффлер
Я думаю, что sortрешения могут быть лучше для большого объема данных (ОП был обеспокоен «хранением всего файла в памяти»). sortвыполнит сортировку вне ядра, если данные больше доступной памяти.
Кусалананда
0

В последней части ответа, упомянутой в: Печать уникальных строк @Gilles в качестве ответа на этот вопрос, я попытался устранить необходимость использования двух хешей.

Это решение для: Для печати только уникальных строк, в порядке их первого появления:

awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'

Здесь «counter» хранит количество каждой строки, аналогичное тому, которое было обработано ранее.
В конце мы печатаем только те строки, у которых значение счетчика равно 1.

Сарфрааз Ахмед
источник