Lapisan satu ini menghapus garis duplikat dari input teks tanpa pra-sortasi.
Sebagai contoh:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
Kode asli yang saya temukan di internet berbunyi:
awk '!_[$0]++'
Ini bahkan lebih membingungkan bagi saya karena saya mengambil _
arti khusus dalam awk, seperti di Perl, tetapi ternyata hanya nama array.
Sekarang, saya mengerti logika di balik one-liner: setiap baris input digunakan sebagai kunci dalam array hash, dengan demikian, setelah selesai, hash berisi garis-garis unik dalam urutan kedatangan.
Yang ingin saya pelajari adalah bagaimana tepatnya notasi ini ditafsirkan oleh awk. Misalnya apa arti tanda bang ( !
) dan elemen lain dari cuplikan kode ini.
Bagaimana cara kerjanya?
Jawaban:
Ayo lihat,
pertama
kita melihat nilai dari
a[$0]
(arraya
dengan seluruh baris input ($0
) sebagai kunci).Jika tidak ada (
!
negasi dalam ujian akan mengevaluasi kebenarannya)kami mencetak baris input
$0
(tindakan default).Kami juga menambahkan satu (
++
) kea[$0]
, jadi lain kali!a[$0]
akan bernilai false.Bagus, temukan !! Anda harus melihat kode golf!
sumber
awk
sebagai tes untuk setiap baris input; setiap kali tes berhasilawk
mengeksekusi aksi dalam kurung kurawal, yang bila dihilangkan adalah{print}
. Terima kasih!awk
, tindakan defaultnya adalah{print $0}
. Ini berarti bahwa apa pun yang dievaluasi sebagai true akan menjalankan ini sebagai default. Jadi misalnyaawk '1' file
mencetak semua baris,awk '$1' file
mencetak semua baris yang bidang pertama tidak kosong atau 0, dll.Berikut ini prosesnya:
a[$0]
: lihat nilai kunci$0
, dalam array asosiatifa
. Jika tidak ada, buatlah.a[$0]++
: increment nilaia[$0]
, kembalikan nilai lama sebagai nilai ekspresi. Jikaa[$0]
tidak ada, kembali0
dan naika[$0]
ke1
(++
operator mengembalikan nilai numerik).!a[$0]++
: meniadakan nilai ekspresi. Jikaa[$0]++
kembali0
, seluruh ekspresi dievaluasi ke true, lakukanawk
tindakan default yang dilakukanprint $0
. Kalau tidak, seluruh ekspresi dievaluasi menjadi false, menyebabkanawk
tidak melakukan apa pun.Referensi:
Dengan
gawk
, kita dapat menggunakan dgawk (atauawk --debug
dengan versi yang lebih baru) untuk men-debuggawk
skrip. Pertama, buatgawk
skrip, beri namatest.awk
:Lalu lari:
atau:
Di konsol debugger:
Anda bisa lihat,
Op_postincrement
sudah dieksekusi sebelumnyaOp_not
.Anda juga dapat menggunakan
si
ataustepi
bukannyas
ataustep
untuk melihat lebih jelas:sumber
!
sudah diterapkan sebelumnya++
.!
operator dihitung. Anda membingungkan prioritas operator (!a[$0]++
diurai seperti!(a[$0]++)
) dengan urutan evaluasi (penugasan nilai barua[$0]
terjadi setelah nilai ekspresi dihitung).!x
dihitung, di manax
nilai lamaa[$0]
. Kemudiana[$0]
diatur ke1+x
.