Perintah itu hanya akan mencetak nilai sekali meskipun itu muncul berkali-kali

8

Saya memiliki file txt besar di mana nilainya berulang berulang kali. Apakah ada beberapa perintah yang bisa saya gunakan yang akan melalui file dan jika satu nilai muncul sekali jangan ulangi lagi?

SO4
HOH
CL
BME
HOH
SO4
HOH
CL
BME
HOH
SO4
HOH
SO4
HOH
CL
BME
HOH
SO4
HOH
CL
BME
HOH
CL

Jadi seharusnya terlihat seperti ini:

S04   
HOH  
CL   
BME 

Masalahnya adalah saya memiliki sejumlah besar nilai yang berbeda, jadi tidak bisa melakukannya secara manual seperti di sini.

djordje
sumber

Jawaban:

11

Anda dapat menggunakan perintah sortdengan opsi --unique:

sort -u input-file

Jika Anda ingin menulis hasil ke FILE alih-alih output standar, gunakan opsi --output=FILE:

sort -u input-file -o output-file

Perintah uniqjuga bisa diterapkan. Dalam hal ini, baris yang identik harus konsekuensial, sehingga input harus diurutkan lebih awal - terima kasih kepada @RonJohn untuk catatan ini :

sort input-file | uniq > output-file

Saya suka sortperintah untuk kasus serupa, karena kesederhanaannya, tetapi jika Anda bekerja dengan array yang besar, awkpendekatan dari jawaban John1024 bisa lebih kuat. Berikut ini adalah perbandingan waktu antara pendekatan yang disebutkan, diterapkan pada file (berdasarkan contoh di atas) dengan hampir 5 juta baris:

$ cat input-file | wc -l
20000000

$ TIMEFORMAT=%R
$ time sort -u input-file | wc -l
64
7.495

$ time sort input-file | uniq | wc -l
64
7.703

$ time awk '!a[$0]++' input-file | wc -l      # from John1024's answer
64
1.271

$ time datamash rmdup 1 < input-file | wc -l  # from αғsнιη's answer
64
0.770

Perbedaan signifikan lainnya adalah yang disebutkan oleh @Ruslan :

sort -uhanya akan mencetak hasil setelah input berakhir, sementara awkperintah ini akan mencetak setiap baris hasil baru dengan cepat (ini mungkin lebih penting untuk input yang disalurkan daripada file).

Berikut ini ilustrasi:

masukkan deskripsi gambar di sini

Dalam contoh di atas, loop (ditampilkan di bawah) menghasilkan 500 kombinasi acak, masing-masing dengan panjang tiga karakter, dari huruf AD. Kombinasi ini disalurkan ke awkatau sort.

for i in {1..500}; do cat /dev/urandom | tr -dc A-D | head -c 3; echo; done
pa4080
sumber
1
Ini perintah yang sangat sederhana! Terimakasih banyak! Semua yang terbaik.
djordje
2
Oh, untuk hari-hari ketika satu utilitas melakukan satu hal dan melakukannya dengan baik !! sort input-file | uniq!!!!
RonJohn
15

Jika Anda ingin menjaga jalur output dalam urutan yang sama dengan jalur input, gunakan:

$ awk '!a[$0]++' file
SO4
HOH
CL
BME

Bagaimana itu bekerja:

Ini menggunakan array asosiatif auntuk menghitung berapa kali setiap baris telah dilihat sebelumnya. Jika belum pernah terlihat sebelumnya, garis dicetak.

John1024
sumber
2
Ini sangat rumit awk, tetapi sort -umerupakan cara yang mudah.
Pierre François
4
@ PierreFrançois, tetapi sort -ujuga merupakan cara paling lambat :) Saya telah memperbarui jawaban saya dengan perbandingan waktu antara kedua pendekatan.
pa4080
4
Juga, sort -uhanya akan mencetak hasil setelah input berakhir, sementara awkperintah ini akan mencetak setiap baris hasil baru dengan cepat (ini mungkin lebih penting untuk input yang disalurkan daripada file).
Ruslan
Terima kasih atas catatan ini, @Ruslan! Saya sudah mencoba mengilustrasikannya dalam jawaban saya.
pa4080
Saya harus mengakui bahwa awksolusinya sangat bagus, walaupun tidak mudah dibaca sort.
Pierre François
1

Anda dapat menggunakan GNU di datamash sini juga sebagai berikut, dan akan menjaga urutannya.

datamash rmdup 1 < infile
αғsнιη
sumber
1
Menurut time perbandingan, ini adalah solusi tercepat, yang disediakan di sini.
pa4080