Hapus garis duplikat yang berdekatan sambil menjaga pesanan

11

Saya memiliki file dengan satu kolom dengan nama yang berulang beberapa kali. Saya ingin menyingkat setiap pengulangan menjadi satu, sambil menjaga pengulangan lainnya dengan nama yang sama yang tidak berdekatan dengan pengulangan lainnya dengan nama yang sama.

Misalnya saya ingin mengubah sisi kiri ke sisi kanan:

Golgb1    Golgb1    
Golgb1    Akna
Golgb1    Spata20
Golgb1    Golgb1
Golgb1    Akna
Akna
Akna
Akna
Spata20
Spata20
Spata20
Golgb1
Golgb1
Golgb1
Akna
Akna
Akna

Inilah yang telah saya gunakan: perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt Namun, metode ini hanya membuat satu perwakilan dari kiri (yaitu Golb1 dan Akna tidak diulang).

Apakah ada cara untuk menyimpan nama-nama unik untuk setiap blok, sambil menjaga nama-nama yang berulang dalam beberapa blok yang tidak berdekatan?

Umur87
sumber

Jawaban:

23

uniq akan melakukan ini untuk Anda:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna
DopeGhoti
sumber
2
wow itu mudah sekali! Terima kasih!
Usia 87
@ Age87 Unix hebat! Ini hanya berfungsi karena Anda mengharapkan duplikat berdekatan, sudah (atau, tidak ingin menghapus yang tidak berdekatan). Biasanya, rekomendasinya adalah menggunakansort | uniq
jpaugh
1
Atau lebih ringkasnya, sort -u(:
DopeGhoti
9

Awk larutan:

awk '$1 != name{ print }{ name = $1 }' file.txt

Hasil:

Golgb1
Akna
Spata20
Golgb1
Akna
RomanPerekhrest
sumber
6

Coba ini - simpan baris sebelumnya dan bandingkan dengan baris saat ini

$ perl -ne 'print if $p ne $_; $p=$_' ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

Anda telah menandai uniqjuga - apakah Anda mencobanya?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna
Sundeep
sumber
1

Dengan sed itu bisa dilakukan sebagai berikut:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Di sini kita miliki di ruang pola setiap saat 2 baris. Ketika perbandingan di antara mereka gagal, kami mencetak yang pertama dan memotongnya dari depan dan kembali dan menambahkan baris berikutnya ke dalam ruang pola. Bilas ... ulangi

Memanfaatkan Perl dalam mode slurp kami memperlakukan seluruh file sebagai satu string panjang di mana regex diterapkan yang melakukan perbandingan untuk Anda.

perl -0777pe 's//$1/ while /^(.*\n)\1+/gm' input_file
Rakesh Sharma
sumber
0

Pertanyaan tentang solusi sed Rakesh Sharma.

Bagaimana jika Anda memiliki file input seperti:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.118 48.216
-126.128 48.222
-126.136 48.226

Dan Anda ingin file output menjadi:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.128 48.222
-126.136 48.226

Perhatikan yang hilang:

-126.118 48.216

Saya tahu perintah yang saya inginkan mirip dengan solusi Anda:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Tidak dapat mengubahnya dengan cara yang benar untuk mencetak kedua kolom dan hanya diurutkan dengan cara khusus ini dengan nilai kolom 2. Ada tips?

Mat
sumber
sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' akan menghapus elemen berulang berikutnya. Catatan: Ini membutuhkan GNU sed. Untuk POSIXperilaku, perlu sedikit perubahan.
Rakesh Sharma