Mencetak garis yang unik


15

Apakah ada solusi yang lebih baik untuk mencetak garis unik selain kombinasi dari sortdan uniq?


1
Apa yang Anda maksud dengan "lebih baik"?
gabe.

@ gabe Tidak memerlukan seluruh file untuk disimpan dalam memori misalnya.
Let_Me_Be

Beberapa versi sort(mis. GNU coreutils) menggunakan file temporer dan mergesort eksternal jika inputnya terlalu besar untuk muat dalam RAM. Dan sebagian besar versi lain memiliki -mopsi sehingga ini dapat dilakukan secara eksplisit dengan memotong input (mis. Dengan split), menyortir setiap chunk, dan kemudian menggabungkan chunks
jhnc

Jawaban:


25

Untuk mencetak setiap garis yang identik hanya satu, dengan urutan apa pun:

sort -u

Untuk mencetak hanya garis-garis unik, dalam urutan apa pun:

sort | uniq -u

Untuk mencetak setiap garis yang identik hanya satu kali, sesuai urutan kemunculan pertama mereka: (untuk setiap baris, cetak garis jika belum terlihat, maka dalam setiap kasus menambah penghitung yang terlihat)

awk '!seen[$0] {print}
     {++seen[$0]}'

Untuk mencetak hanya garis-garis unik, sesuai urutan kemunculan pertama mereka: (catat setiap baris seen, dan juga linesjika itu adalah kejadian pertama; pada akhir input, cetak garis sesuai urutan kejadian, tetapi hanya yang terlihat hanya sekali)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'

8
bagaimana awk '!seen[$0]++ {print}'?
asoundmove

10
Atau bahkan lebih pendek awk '!seen[$0]++', karena {print}tersirat oleh perintah kosong.
quazgar

3

Beberapa (sebagian besar?) Versi sortmemiliki -ubendera yang melakukan uniqbagian secara langsung. Mungkin ada beberapa batasan panjang garis tergantung pada implementasinya, tetapi Anda sudah memilikinya dengan polos sort|uniq.


1
Eh? sort -ukembali ke V7 setidaknya.
geekosaur

Hum ... Saya pikir saya ingat Solaris atau AIX tidak memilikinya. Tapi saya salah, mereka berdua memilikinya.
Mat

Solaris dan AIX memiliki -utetapi juga memiliki batasan panjang garis 512 karakter. (Sebenarnya, saya pikir di sekitar Solaris 9, Sun menaikkannya menjadi 5120. Namun, GNU masih menang.)
geekosaur

@geekosaur: Anda yakin? Pekerjaan yang dilakukan untuk menghapus batas 512 byte pada panjang garis dalam bentuk didokumentasikan dalam 'Teori dan Praktek dalam Konstruksi Rutin Sortir Kerja' oleh JP Linderman, Bell System Technical. Jurnal, 63, 1827-1843 (1984).
Jonathan Leffler

0

Apakah Perl bekerja untuk Anda? Itu dapat menjaga garis dalam urutan asli, bahkan jika duplikat tidak berdekatan Anda juga bisa memberi kode dengan Python, atau awk.

while (<>) {
    print if $lines{$_}++ == 0;
}

Yang bisa disingkat menjadi adil

perl -ne 'print unless $lines{$_}++;'

File input yang diberikan:

abc
def
abc
ghi
abc
def
abc
ghi
jkl

Ini menghasilkan output:

abc
def
ghi
jkl

Di mana $ lines didefinisikan?
Gregg Leventhal

Bukan itu. Karena tidak ada use strict;atau use warnings;(sebenarnya, itu strictyang paling relevan di sini), tidak ada keluhan tentang penggunaan %linessebelum didefinisikan. Jika dijalankan dengan striktur, harus ada garis my %lines;sebelum loop. Perhatikan juga, bahwa hash adalah %lines; satu elemen dari hash dirujuk menggunakan $lines{$_}notasi.
Jonathan Leffler

Saya pikir sortsolusinya mungkin lebih baik untuk sejumlah besar data (OP khawatir tentang "menyimpan seluruh file dalam memori"). sortakan melakukan semacam out-of-core jika data lebih besar dari memori yang tersedia.
Kusalananda

0

Untuk bagian terakhir dari jawaban yang disebutkan dalam: Mencetak baris unik oleh @Gilles sebagai jawaban untuk pertanyaan ini, saya mencoba menghilangkan kebutuhan untuk menggunakan dua hash.

Solusi ini adalah untuk: Untuk mencetak hanya garis-garis unik, sesuai urutan kemunculannya yang pertama:

awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'

Di sini, "penghitung" menyimpan hitungan setiap baris yang mirip dengan yang diproses sebelumnya.
Pada akhirnya, kami hanya mencetak garis-garis itu, yang memiliki nilai berlawanan sebagai 1.

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.