Bagaimana cara mendapatkan hanya hasil unik tanpa harus mengurutkan data?


40
$ cat data.txt 
aaaaaa
aaaaaa
cccccc
aaaaaa
aaaaaa
bbbbbb
$ cat data.txt | uniq
aaaaaa
cccccc
aaaaaa
bbbbbb
$ cat data.txt | sort | uniq
aaaaaa
bbbbbb
cccccc
$

Hasil yang saya butuhkan adalah untuk menampilkan semua baris dari file asli menghapus semua duplikat (bukan hanya yang berturut-turut), sambil mempertahankan urutan pernyataan asli dalam file .

Di sini, dalam contoh ini, hasil yang sebenarnya saya cari adalah

aaaaaa
cccccc
bbbbbb

Bagaimana saya bisa melakukan uniqoperasi umum ini secara umum?

Jawaban:


54
perl -ne 'print unless $seen{$_}++' data.txt

Atau, jika Anda harus menggunakancat :

cat data.txt | perl -ne 'print unless $seen{$_}++'

Berikut ini adalah awkterjemahan, untuk sistem yang tidak memiliki Perl:

awk '!seen[$0]++' data.txt
cat data.txt | awk '!seen[$0]++'

3
Script awk yang sedikit lebih pendek adalah{ if (!seen[$0]++) print }
camh

1
@ Fred, kecuali file Anda benar-benar besar, versi mana pun membutuhkan waktu lebih lama untuk mengetik daripada menjalankannya.
cjm

8
Versi awk dapat dibuat bahkan lebih pendek dengan meninggalkan keluar if, print, kurung, dan kawat gigi:awk '!seen[$0]++'
Gordon Davisson

2
@ Legate, ini adalah nama array yang kami gunakan untuk merekam setiap baris yang kami lihat. Anda bisa mengubahnya ke '!LarryWall[$0]++'untuk semua awk peduli, tetapi "terlihat" membantu orang memahami program dengan lebih baik.
cjm

1
@Sadi, itu seharusnya ditanyakan sebagai pertanyaan, bukan komentar. Tetapi beberapa baris dalam file itu berakhir di spasi, dan beberapa tidak. Perintah-perintah ini menganggap seluruh baris signifikan, termasuk spasi di akhir.
cjm

13

john memiliki alat yang disebut unique:

usr@srv % cat data.txt | unique out
usr@srv % cat out
aaaaaa
cccccc
bbbbbb

Untuk mencapai hal yang sama tanpa alat tambahan dalam satu commandline sedikit lebih kompleks:

usr@srv % cat data.txt | nl | sort -k 2 | uniq -f 1 | sort -n | sed 's/\s*[0-9]\+\s\+//'
aaaaaa
cccccc
bbbbbb

nlmencetak nomor baris di depan garis, jadi jika kita sort/ di uniqbelakangnya, kita dapat mengembalikan urutan asli garis. sedhanya menghapus nomor baris sesudahnya;)


apakah ada kombinasi perintah linux umum yang bisa melakukan hal yang sama?
Lazer

7
Apa yang Anda lewatkan dalam "tanpa harus mengurutkan data"?
Totor

@Totor - lihat menkus ' balasan untuk komentar serupa. @ binfalse - solusi kedua Anda tidak bekerja (mungkin ini bekerja dengan sampel sepele ini tetapi tidak bekerja dengan beberapa input kehidupan nyata). Harap perbaiki itu, mis. Ini harus selalu berfungsi:nl -ba -nrz data.txt | sort -k2 -u | sort | cut -f2
don_crissti

6

Saya lebih suka menggunakan ini:

cat -n data.txt | sort --key=2.1 -b -u | sort -n | cut -c8-

cat -n menambahkan nomor baris,

sort --key=2.1 -b -u mengurutkan pada bidang kedua (setelah nomor baris yang ditambahkan), mengabaikan baris awal, menjaga garis yang unik

sort -n mengurutkan dalam urutan numerik yang ketat

cut -c8- jauhkan semua karakter dari kolom 8 hingga EOL (mis. hilangkan nomor baris yang kami sertakan)


5
> Bagaimana cara mendapatkan hasil yang unik tanpa harus mengurutkan data? > tanpa harus mengurutkan data
Jan Wikholm

7
'tanpa harus menyortir data' hanya muncul dalam judul. Kebutuhan sebenarnya adalah: "menampilkan semua baris dari file asli menghapus semua duplikat (bukan hanya yang berturut-turut), sambil mempertahankan urutan pernyataan asli dalam file."
menkus

1
@menkus kuncinya adalah "sambil mempertahankan urutan asli pernyataan dalam file". Jawaban ini tidak mencapai itu.
Andrew Ferrier

2

Perl memiliki modul yang dapat Anda gunakan yang mencakup fungsi yang disebut uniq. Jadi jika Anda ave data Anda dimuat dalam array di Perl Anda cukup memanggil fungsi seperti ini untuk membuatnya unik, namun tetap mempertahankan urutan aslinya.

use List::MoreUtils qw(uniq)    
@output = uniq(@output);

Anda dapat membaca lebih lanjut tentang modul ini di sini: Daftar :: MoreUtils


Bisakah ini menangani file besar, misalnya 500 GB?
Anak laki
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.