Найти дубликаты строк в файле и посчитать, сколько раз каждая строка дублировалась?

529

Предположим, у меня есть файл, подобный следующему:

123 
123 
234 
234 
123 
345

Я хотел бы выяснить, сколько раз дублировалось значение «123», сколько раз дублировалось значение «234» и т. Д. Поэтому в идеале вывод должен выглядеть следующим образом:

123  3 
234  2 
345  1
user839145
источник
4
Какой язык вы хотите использовать?
VMAtm

Ответы:

791

Предполагая, что есть одна цифра в строке:

sort <file> | uniq -c

Вы также можете использовать более подробный --countфлаг с версией GNU, например, в Linux:

sort <file> | uniq --count
wonk0
источник
3
Это то, что я делаю, однако алгоритмически это не самый эффективный подход (O (n log n) * avg_line_len, где n - количество строк). Я работаю с файлами размером несколько гигабайт, поэтому ключевым моментом является производительность. Интересно, есть ли инструмент, который выполняет только подсчет за один проход, используя дерево префиксов (в моем случае строки часто имеют общие префиксы) или аналогичный, который должен добиться цели в O (n) * avg_line_len. Кто-нибудь знает такой инструмент командной строки?
Дроггл
21
Дополнительным шагом является передача выходных данных в окончательную команду sort -n. Это позволит отсортировать результаты, по которым строки встречаются чаще всего.
Самоз
79
Если вы хотите печатать только дубликаты строк, используйте 'uniq -d'
DmitrySandalov
6
Если вы хотите снова отсортировать результат, вы можете использовать sortснова, как:sort <file> | uniq -c | sort -n
Abhishek
414

Это будет печатать только дубликаты строк с количеством:

sort FILE | uniq -cd

или с длинными параметрами GNU (в Linux):

sort FILE | uniq --count --repeated

в BSD и OSX вы должны использовать grep для фильтрации уникальных строк:

sort FILE | uniq -c | grep -v '^ *1 '

Для данного примера результатом будет:

  3 123
  2 234

Если вы хотите напечатать счетчики для всех строк, включая те, которые появляются только один раз:

sort FILE | uniq -c

или с длинными параметрами GNU (в Linux):

sort FILE | uniq --count

Для данного входа, выход:

  3 123
  2 234
  1 345

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

sort FILE | uniq -c | sort -nr

или, чтобы получить только повторяющиеся строки, чаще всего сначала:

sort FILE | uniq -cd | sort -nr

на OSX и BSD финальным становится:

sort FILE | uniq -c | grep -v '^ *1 ' | sort -nr
Andrea
источник
1
Хороший вопрос с опцией --repeated или -d. Намного точнее, чем использовать "| grep 2" или подобное!
Лаури
Как я могу изменить эту команду, чтобы получить все строки с числом повторений более 100?
Black_Rider
@Black_Rider При добавлении | sort -nили | sort -nrв трубу вывод сортируется по количеству повторений (по возрастанию или по убыванию соответственно). Это не то, что вы спрашиваете, но я подумал, что это может помочь.
Андреа
1
@Black_Rider awk, кажется, в состоянии сделать все виды вычислений: в вашем случае вы могли бы сделать| awk '$1>100'
Андреа
4
@fionbio Похоже, вы не можете использовать -c и -d вместе в OSX uniq . Спасибо за указание. Вы можете использовать grep для фильтрации уникальных строк :sort FILE | uniq -c | grep -v '^ *1 '
Andrea
72

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

sort <files> | uniq -c | sort -nr

или:

cat <files> | sort | uniq -c | sort -nr
kenorb
источник
30

Через :

awk '{dups[$1]++} END{for (num in dups) {print num,dups[num]}}' data

В awk 'dups[$1]++'команде переменная $1содержит все содержимое column1, а квадратные скобки - доступ к массиву. Таким образом, для каждого 1-го столбца строки в dataфайле узел названного массива dupsувеличивается.

И, наконец , мы перебираем dupsмассив с numпеременной as и печатаем сначала сохраненные числа, а затем их количество дублированных значений dups[num].

Обратите внимание, что у вашего входного файла есть пробелы в конце некоторых строк, если вы очистите их, вы можете использовать $0вместо $1команды выше :)

αғsнιη
источник
1
Разве это не немного излишне, учитывая, что у нас есть uniq?
Натан Феллман
9
sort | uniqи у решения awk совсем другой компромисс между производительностью и ресурсами: если файлы большие, а количество разных строк невелико, решение awk намного эффективнее. Он линейный по количеству строк, а использование пространства линейно по количеству разных строк. OTOH, решение awk должно хранить все различные строки в памяти, в то время как сортировка (GNU) может использовать временные файлы.
Ларс Нощинский
14

В Windows, используя Windows PowerShell, я использовал команду, указанную ниже, чтобы добиться этого

Get-Content .\file.txt | Group-Object | Select Name, Count

Также мы можем использовать командлет where-object для фильтрации результатов

Get-Content .\file.txt | Group-Object | Where-Object { $_.Count -gt 1 } | Select Name, Count
vineel
источник
Вы можете удалить все вхождения дубликатов, кроме последнего ... без изменения порядка сортировки файла?
jparram
6

Предполагая, что у вас есть доступ к стандартной оболочке Unix и / или среде cygwin:

tr -s ' ' '\n' < yourfile | sort | uniq -d -c
       ^--space char

В основном: конвертируйте все пробелы в разрывы строк, затем сортируйте транслированные выходные данные и передавайте их в uniq и подсчитывайте повторяющиеся строки.

Марк Б
источник