Знайдіть дублікати рядків у файлі і порахуйте, скільки разів дублюється кожен рядок?


529

Припустимо, у мене є файл, подібний до наступного:

123 
123 
234 
234 
123 
345

Я хотів би дізнатися, скільки разів дублювали «123», скільки разів «234» дублювали і т. Д. Тож в ідеалі результат буде таким:

123  3 
234  2 
345  1

4
Якою мовою ви хочете користуватися?
VMAtm

Відповіді:


791

Припустимо, що є одне число на рядок:

sort <file> | uniq -c

Ви також можете використовувати більш багатослівний --countпрапор також у версії GNU, наприклад, в Linux:

sort <file> | uniq --count

3
Це те, що я роблю, але алгоритмічно це, здається, не є найбільш ефективним підходом (O (n log n) * avg_line_len, де n - кількість рядків). Я працюю над файлами, які мають кілька гігабайт, тому продуктивність є ключовою проблемою. Мені цікаво, чи є інструмент, який виконує просто підрахунок в одному пропуску за допомогою дерева префіксів (у моєму випадку рядки часто мають загальні префікси) або подібний, який повинен зробити трюк в O (n) * avg_line_len. Хтось знає такий інструмент командного рядка?
Droggl

21
Додатковим кроком є ​​передача результату цього в остаточну команду 'sort -n'. Це дозволить сортувати результати, за якими рядки трапляються найчастіше.
samoz

79
Якщо ви хочете друкувати лише повторювані рядки, використовуйте 'uniq -d'
Дмитро Сандалов

6
Якщо ви знову хочете сортувати результат, ви можете sortзнову використовувати :sort <file> | uniq -c | sort -n
Абхішек

413

Це надрукує лише повторювані рядки з підрахунками:

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

1
Хороший момент з опцією - повторення або -d. Настільки точніше, ніж використання "| grep 2" або подібного!
Лаурі

Як я можу змінити цю команду для отримання всіх рядків, кількість повторень яких перевищує 100?
Black_Rider

@Black_Rider Додавання | sort -nабо | sort -nrв трубу буде сортувати вихід за кількістю повторень (відповідно або по убуванню). Ви це не просите, але я думав, що це може допомогти.
Андреа

1
@Black_Rider awk, здається, здатний робити всілякі обчислення: у вашому випадку ви могли б це зробити| awk '$1>100'
Андреа


72

Щоб знайти і підрахувати повторювані рядки в декількох файлах, ви можете спробувати наступну команду:

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

або:

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

30

Віа :

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

У awk 'dups[$1]++'команді змінна $1вміщує весь вміст стовпця1, а квадратні дужки мають доступ до масиву. Отже, для кожного 1-го стовпця рядка у dataфайлі dupsзбільшується вузол названого масиву .

І наприкінці ми перебираємо dupsмасив із numмінливою мінливою величиною і надрукуємо збережені числа спочатку, а потім їх кількість, що дублюється, на dups[num].

Зауважте, що у вашому вхідному файлі є пробіли на кінці деяких рядків, якщо ви очистите їх, ви можете використовувати $0замість $1команди вище :)


1
Хіба це не є трохи зайвим, враховуючи, що у нас є uniq?
Натан Феллман

9
sort | uniqі рішення awk мають зовсім інші продуктивні та компромісні ресурси: якщо файлів велике, а кількість різних рядків невелика, рішення awk набагато ефективніше. Він лінійний за кількістю рядків, а використання простору - лінійним у кількості різних ліній. ОТО, рішення awk потребує збереження всіх різних рядків у пам’яті, тоді як (GNU) сортування може вдаватися до тимчасових файлів.
Ларс Нощинський

14

У Windows, що використовує "Windows PowerShell", я досягнув цієї команди

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

Також ми можемо використовувати Cmdlet де-об'єкта для фільтрації результату

Get-Content .\file.txt | Group-Object | Where-Object { $_.Count -gt 1 } | Select Name, Count

чи можна видалити всі випадки дублікатів, крім останнього ... без зміни порядку сортування файлу?
jparram

6

Припустимо, що у вас є доступ до стандартної оболонки Unix та / або середовища cygwin:

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

В основному: перетворіть всі символи простору в рядкові розбиття, потім сортуйте трансляційний вихід і подайте їх на uniq та підрахуйте повторювані рядки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.