GNU/Linux >> Belajar Linux >  >> Linux

Hapus Bidang Duplikat Di Kolom yang Diberikan?

Saya ingin menghapus dari kolom tertentu ($2 dalam contoh) bidang duplikat (dipisahkan koma).

Berkas masukan:

A    1,2,3,4   
B    4,5,6,3
C    2,15

Hasil yang diharapkan:

A    1,2,3,4
B    5,6
C    15

Jawaban yang Diterima:

perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e'

Anda dapat menjalankan yang di atas seperti ini:

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e' afile 
A    1,2,3,4
B    5,6
C    15

Cara kerjanya

Panggilan pertama perl dengan -lpe melakukan 3 hal berikut.

  • -l[octal] aktifkan pemrosesan akhir baris, tentukan terminator baris
  • -p asumsikan loop seperti -n tetapi juga cetak baris, seperti sed
  • -e program satu baris program (beberapa -e diperbolehkan, hilangkan file program)

Ini pada dasarnya mengambil file, menghapus baris baru, beroperasi pada satu baris, dan kemudian menempelkan karakter baris baru kembali ke dalamnya setelah selesai. Jadi itu hanya mengulang file dan mengeksekusi kode Perl kami satu per satu secara bergantian.

Adapun kode Perl yang sebenarnya:

  • s berarti karakter spasi (lima karakter [ fnrt] dan v dalam versi perl yang lebih baru , seperti [[:space:]] ).
  • K Simpan barang-barang di kiri K, jangan sertakan di $&
  • S+ satu atau lebih karakter tidak ada dalam kumpulan [ fnrtv]

join ",", akan mengambil hasilnya dan menggabungkan kembali setiap bidang sehingga dipisahkan dengan koma.

split ",", $& akan mengambil kecocokan yang ditemukan oleh S+ dan pisahkan menjadi kolom saja, tanpa koma.

grep {!$seen{$_}++} akan mengambil nomor setiap bidang, menambahkannya ke hash, $seen{} di mana nomor setiap bidang adalah $_ saat kita melewatinya masing-masing. Setiap kali nomor bidang "dilihat" itu dihitung melalui ++ operator, $seen{$_}++ .

grep{!$seen{$_}++} akan mengembalikan nilai bidang jika hanya dilihat sekali.

Dimodifikasi untuk melihat apa yang terjadi

Jika Anda menggunakan kekejian yang dimodifikasi ini, Anda dapat melihat apa yang terjadi saat Perl one liner ini bergerak melintasi baris dari file.

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e; @a=keys %seen; @b=values %seen; print "keys: @a | vals: @b"' afile 
keys: 4 1 3 2 | vals: 1 1 1 1
A    1,2,3,4
keys: 6 4 1 3 2 5 | vals: 1 2 1 2 1 1
B    5,6
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1
C    15

Ini menunjukkan kepada Anda konten $seen{} di akhir pemrosesan satu baris dari file. Mari kita ambil baris ke-2 dari file tersebut.

B    4,5,6,3

Dan inilah yang versi modifikasi saya menunjukkan baris itu sebagai:

keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1

Jadi ini mengatakan bahwa kita telah melihat bidang # 6 (1 kali), bidang # 4 (2 kali), dll. dan bidang # 5 (1 kali). Jadi ketika grep{...} mengembalikan hasil itu hanya akan mengembalikan hasil dari array ini jika ada di baris ini (4,5,6,3) dan jika kita melihatnya hanya 1 kali (6,1,15,5). Perpotongan dari 2 daftar ini adalah (5,6) dan itulah yang dikembalikan oleh grep .

Referensi

  • perlre – perldoc.perl.org
Terkait:Cara memodifikasi file di tempat?
Linux
  1. Hapus Garis Duplikat yang Berdekatan Sambil Menjaga Pesanan?

  2. Apakah ada cara untuk 'uniq' dengan kolom?

  3. Cara menggandakan folder dengan tepat

  1. Cara Menemukan dan Menghapus Foto Duplikat di Linux

  2. Hapus kunci yang kedaluwarsa di APT

  3. Bagaimana Cara Menghapus Garis Duplikat Di Dalam File Teks?

  1. Hapus Garis Berdasarkan Duplikat Dalam Satu Kolom Tanpa Urutkan?

  2. Cetak Garis Jika Kolom Diberikan Dimulai Dengan Huruf Kapital?

  3. Urutkan Output Berdasarkan Kolom?