Temukan baris duplikat dalam file dan hitung berapa kali setiap baris digandakan?

529

Misalkan saya memiliki file yang mirip dengan yang berikut:

123 
123 
234 
234 
123 
345

Saya ingin menemukan berapa kali '123' digandakan, berapa kali '234' digandakan, dll. Jadi idealnya, hasilnya akan seperti:

123  3 
234  2 
345  1
pengguna839145
sumber
4
Bahasa apa yang ingin Anda gunakan?
VMAtm

Jawaban:

791

Dengan asumsi ada satu nomor per baris:

sort <file> | uniq -c

Anda dapat menggunakan --countflag yang lebih verbose juga dengan versi GNU, misalnya, di Linux:

sort <file> | uniq --count
wonk0
sumber
3
Namun inilah yang saya lakukan secara algoritmik. Ini sepertinya bukan pendekatan yang paling efisien (O (n log n) * avg_line_len di mana n adalah jumlah baris). Saya sedang mengerjakan file yang berukuran beberapa gigabytes, jadi kinerja adalah masalah utama. Saya bertanya-tanya apakah ada alat yang menghitung hanya dalam satu pass menggunakan pohon awalan (dalam kasus saya string sering memiliki awalan umum) atau serupa, yang seharusnya melakukan trik di O (n) * avg_line_len. Apakah ada yang tahu alat commandline seperti itu?
Droggl
21
Langkah tambahan adalah menyalurkan output itu ke perintah 'sort -n' akhir. Itu akan mengurutkan hasil dimana garis paling sering muncul.
samoz
79
Jika Anda hanya ingin mencetak garis duplikat, gunakan 'uniq -d'
DmitrySandalov
6
Jika Anda ingin kembali mengurutkan hasilnya, Anda dapat menggunakan sortlagi seperti:sort <file> | uniq -c | sort -n
Abhishek Kashyap
414

Ini akan mencetak garis duplikat saja , dengan jumlah:

sort FILE | uniq -cd

atau, dengan opsi panjang GNU (di Linux):

sort FILE | uniq --count --repeated

pada BSD dan OSX Anda harus menggunakan grep untuk memfilter baris unik:

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

Untuk contoh yang diberikan, hasilnya adalah:

  3 123
  2 234

Jika Anda ingin mencetak jumlah untuk semua baris termasuk yang hanya muncul sekali:

sort FILE | uniq -c

atau, dengan opsi panjang GNU (di Linux):

sort FILE | uniq --count

Untuk input yang diberikan, outputnya adalah:

  3 123
  2 234
  1 345

Untuk mengurutkan output dengan garis paling sering di atas, Anda dapat melakukan hal berikut (untuk mendapatkan semua hasil):

sort FILE | uniq -c | sort -nr

atau, untuk mendapatkan hanya garis duplikat, paling sering terlebih dahulu:

sort FILE | uniq -cd | sort -nr

pada OSX dan BSD yang terakhir menjadi:

sort FILE | uniq -c | grep -v '^ *1 ' | sort -nr
Andrea
sumber
1
Poin bagus dengan opsi --repeat atau -d. Jauh lebih akurat daripada menggunakan "| grep 2" atau serupa!
Lauri
Bagaimana saya bisa memodifikasi perintah ini untuk mengambil semua baris yang jumlah pengulangannya lebih dari 100?
Black_Rider
@ Black_Rider Menambahkan | sort -natau | sort -nrke pipa akan mengurutkan output berdasarkan jumlah pengulangan (masing-masing naik atau turun). Ini bukan yang Anda minta, tetapi saya pikir itu mungkin membantu.
Andrea
1
@Black_Rider awk tampaknya dapat melakukan semua jenis perhitungan: jika Anda dapat melakukannya| awk '$1>100'
Andrea
4
@ fionbio Sepertinya Anda tidak dapat menggunakan -c dan -d bersama di OSX uniq . Terima kasih telah menunjukkan. Anda dapat menggunakan grep untuk memfilter garis-garis unik :sort FILE | uniq -c | grep -v '^ *1 '
Andrea
72

Untuk menemukan dan menghitung garis duplikat di banyak file, Anda dapat mencoba perintah berikut:

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

atau:

cat <files> | sort | uniq -c | sort -nr
kenorb
sumber
30

Melalui :

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

Dalam awk 'dups[$1]++'perintah, variabel $1memegang seluruh isi kolom1 dan tanda kurung siku adalah akses array. Jadi, untuk setiap kolom pertama dari baris dalam datafile, simpul dari array yang dinamai dupsbertambah.

Dan pada akhirnya, kita mengulang dupsarray dengan numvariabel dan mencetak nomor yang disimpan terlebih dahulu kemudian jumlah nilai duplikatnya dups[num].

Perhatikan bahwa file input Anda memiliki spasi di ujung beberapa baris, jika Anda menjernihkannya, Anda dapat menggunakannya $0sebagai pengganti $1perintah di atas :)

αғsнιη
sumber
1
Bukankah ini sedikit berlebihan mengingat yang kita miliki uniq?
Nathan Fellman
9
sort | uniqdan solusi awk memiliki kinerja & pertukaran sumber daya yang sangat berbeda: jika file besar dan jumlah baris yang berbeda kecil, solusi awk jauh lebih efisien. Itu linier dalam jumlah garis dan penggunaan ruang linier dalam jumlah garis yang berbeda. OTOH, solusi awk perlu menyimpan semua baris yang berbeda dalam memori, sementara (GNU) sort dapat menggunakan file temp.
Lars Noschinski
14

Di windows menggunakan "Windows PowerShell" Saya menggunakan perintah yang disebutkan di bawah ini untuk mencapai ini

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

Kita juga bisa menggunakan mana-objek Cmdlet untuk memfilter hasilnya

Get-Content .\file.txt | Group-Object | Where-Object { $_.Count -gt 1 } | Select Name, Count
anggur
sumber
dapatkah Anda menghapus semua kemunculan duplikat kecuali yang terakhir ... tanpa mengubah urutan pengurutan file?
jparram
6

Dengan asumsi Anda memiliki akses ke shell Unix standar dan / atau lingkungan cygwin:

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

Pada dasarnya: konversikan semua karakter spasi menjadi linebreak, lalu urutkan output yang ditranslasikan dan masukkan ke uniq dan hitung garis duplikat.

Marc B
sumber