Jika Anda menjalankan Bash versi 4 atau lebih tinggi (yang seharusnya terjadi pada versi Linux modern), Anda bisa mendapatkan nilai array unik di bash dengan membuat array asosiatif baru yang berisi setiap nilai dari array asli. Sesuatu seperti ini:
$ a=(aa ac aa ad "ac ad")
$ declare -A b
$ for i in "${a[@]}"; do b["$i"]=1; done
$ printf '%s\n' "${!b[@]}"
ac ad
ac
aa
ad
Ini berfungsi karena dalam larik apa pun (asosiatif atau tradisional, dalam bahasa apa pun), setiap kunci hanya dapat muncul sekali. Ketika for
perulangan tiba di nilai kedua dari aa
dalam a[2]
, itu menimpa b[aa]
yang awalnya ditetapkan untuk a[0]
.
Melakukan hal-hal di bash asli bisa lebih cepat daripada menggunakan pipa dan alat eksternal seperti sort
dan uniq
, meskipun untuk kumpulan data yang lebih besar Anda kemungkinan akan melihat kinerja yang lebih baik jika Anda menggunakan bahasa yang lebih kuat seperti awk, python, dll.
Jika Anda merasa yakin, Anda dapat menghindari for
pengulangan dengan menggunakan printf
kemampuan untuk mendaur ulang formatnya untuk beberapa argumen, meskipun ini tampaknya membutuhkan eval
. (Berhenti membaca sekarang jika Anda setuju dengan itu.)
$ eval b=( $(printf ' ["%s"]=1' "${a[@]}") )
$ declare -p b
declare -A b=(["ac ad"]="1" [ac]="1" [aa]="1" [ad]="1" )
Alasan yang dibutuhkan oleh solusi ini eval
adalah karena nilai array ditentukan sebelum pemisahan kata. Itu berarti bahwa output dari substitusi perintah dianggap sebagai kata tunggal daripada sekumpulan pasangan kunci = nilai.
Meskipun ini menggunakan subkulit, ini hanya menggunakan bash bawaan untuk memproses nilai array. Pastikan untuk mengevaluasi penggunaan Anda eval
dengan mata kritis. Jika Anda tidak 100% yakin bahwa chepner atau glenn jackman atau greycat tidak akan menemukan kesalahan pada kode Anda, gunakan loop for sebagai gantinya.
uniq=($(printf "%s\n" "${ids[@]}" | sort -u)); echo "${uniq[@]}"