Ini yang menyenangkan. Anda dapat menggunakan sedsecara langsung untuk menghapus semua salinan dari baris pertama dan meninggalkan semua yang lain di tempatnya (termasuk baris pertama itu sendiri).
sed '1{h;n;};G;/^\(.*\)\n\1$/d;s/\n.*$//' input
1{h;n;}menempatkan baris pertama ke dalam ruang penahanan, mencetaknya, dan membaca di baris berikutnya — melompati sisa sedperintah untuk baris pertama. (Ini juga melewatkan 1tes pertama untuk baris kedua , tetapi itu tidak masalah karena tes itu tidak akan berlaku untuk baris kedua.)
G menambahkan baris baru diikuti dengan isi ruang pegang ke ruang pola.
/^\(.*\)\n\1$/dmenghapus isi dari ruang pola (sehingga melompati ke baris berikutnya) jika bagian setelah baris baru (yaitu apa yang ditambahkan dari ruang penahanan) persis cocok dengan bagian sebelum baris baru. Di sinilah baris yang menduplikasi header akan dihapus.
s/\n.*$//menghapus bagian teks yang ditambahkan oleh Gperintah, sehingga yang dicetak hanyalah baris teks dari file.
Namun, karena regex mahal, pendekatan yang sedikit lebih cepat adalah dengan menggunakan kondisi yang sama (dinegasikan) dan Pnaik ke baris baru jika bagian setelah baris baru (yaitu apa yang ditambahkan dari ruang penahanan) tidak persis cocok dengan porsi sebelum baris baru dan kemudian menghapus tanpa ruang pola:
sed '1{h;n;};G;/^\(.*\)\n\1$/!P;d' input
Output saat diberikan input Anda adalah:
ID Data1 Data2
1 100 100
2 100 200
3 200 100
4 100 100
5 200 200
{ IFS= read -r head; printf '%s\n' "$head"; grep -vF "$head" ; } <file