Saya punya dua array seperti ini:
A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618 vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)
Array tidak diurutkan dan bahkan mungkin mengandung elemen duplikat.
Saya ingin membuat persimpangan dua array ini dan menyimpan elemen dalam array lain. Bagaimana saya melakukannya?
Juga, bagaimana saya mendapatkan daftar elemen yang muncul di B dan tidak tersedia di A?
foo
dua kali), apakah Anda memerlukannya digandakan dalam hasilnya?Jawaban:
comm(1)
adalah alat yang membandingkan dua daftar dan dapat memberi Anda persimpangan atau perbedaan antara dua daftar. Daftar perlu disortir, tetapi itu mudah dicapai.Untuk membuat array Anda ke daftar yang diurutkan cocok untuk
comm
:Itu akan mengubah array A menjadi daftar yang diurutkan. Lakukan hal yang sama untuk B.
Untuk digunakan
comm
untuk mengembalikan persimpangan:-1 -2
mengatakan untuk menghapus entri yang unik untuk file1 (A) dan unik untuk file2 (B) - persimpangan keduanya.Untuk mengembalikannya apa yang ada di file2 (B) tetapi tidak file1 (A):
-1 -3
mengatakan untuk menghapus entri yang unik untuk file1 dan umum untuk keduanya - hanya menyisakan yang unik untuk file2.Untuk memasukkan dua saluran pipa
comm
, gunakan fitur "Substitusi Proses" daribash
:Untuk menangkap ini dalam sebuah array:
Menyatukan semuanya:
sumber
\n
.\n
coba ini:arr1=( one two three "four five\nsix\nseven" ); arr2=( ${arr1[@]:1} "four five\\nsix" ); n1=${#arr1[@]}; n2=${#arr2[@]}; arr=( ${arr1[@]/ /'-_-'} ${arr2[@]/ /'-_-'} ); arr=( $( echo "${arr[@]}"|tr '\t' '-t-'|tr '\n' '-n-'|tr '\r' '-r-' ) ); arr1=( ${arr[@]:0:${n1}} ); arr2=( ${arr[@]:${n1}:${n2}} ); unset arr; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr1[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr2[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n\n'; unset arr1; unset arr2
LC_ALL=C
. Alih-alih ditetapkanLC_COLLATE=C
untuk kenaikan kinerja yang sama tanpa efek samping lainnya. Untuk mendapatkan hasil yang benar, Anda juga perlu mengatur susunan yang sama dengancomm
yang digunakan untuksort
, misalnya:unset LC_ALL; LC_COLLATE=C ; comm -12 <(printf '%s\n' "${A[@]}" | sort) <(printf '%s\n' "${B[@]}" | sort)
Anda bisa mendapatkan semua elemen yang ada di A dan B dengan mengulang melalui kedua array dan membandingkan:
Anda bisa mendapatkan semua elemen dalam B tetapi tidak dalam A dengan cara yang sama:
sumber
A
danB
, apakahintersections
selalu sama dengan menata ulang?Ada pendekatan yang agak elegan dan efisien untuk melakukan itu, menggunakan
uniq
- tetapi, kita perlu menghilangkan duplikat dari setiap array, hanya menyisakan item unik. Jika Anda ingin menyimpan duplikat, hanya ada satu cara "dengan mengulang melalui kedua array dan membandingkan".Pertimbangkan kami memiliki dua array:
Pertama-tama, mari kita ubah array ini menjadi set. Kami akan melakukannya karena ada persimpangan operasi matematika yang terkenal seperti persimpangan set, dan set adalah kumpulan yang berbeda objek, yang berbeda atau unik . Sejujurnya, saya tidak tahu apa itu "persimpangan" jika kita berbicara tentang daftar atau urutan. Meskipun kita dapat memilih urutan berikutnya dari urutan, tetapi operasi ini (pemilihan) memiliki arti yang sedikit berbeda.
Jadi, ayo bertransformasi!
Persimpangan:
Jika Anda ingin menyimpan elemen dalam array lain:
uniq -d
berarti hanya menunjukkan duplikat (saya pikir,uniq
agak cepat karena realisasinya: Saya kira itu dilakukan denganXOR
operasi).Dapatkan daftar elemen yang muncul
B
dan tidak tersedia diA
, yaituB\A
Atau, dengan menyimpan dalam variabel:
Jadi, pada awalnya kita memiliki persimpangan
A
danB
(yang merupakan kumpulan duplikat di antara mereka), katakan demikianA/\B
, dan kemudian kita menggunakan operasi persimpangan simpang dariB
danA/\B
(yang hanya merupakan elemen unik), jadi kita dapatkanB\A = ! (B /\ (A/\B))
.PS
uniq
ditulis oleh Richard M. Stallman dan David MacKenzie.sumber
Mengabaikan efisiensi, berikut ini pendekatannya:
sumber
Cara bash murni saya
Karena variabel ini hanya berisi di
vol-XXX
manaXXX
bilangan heksadesimal, ada cara cepat menggunakan bash arrayIni harus menghasilkan:
Pada kondisi ini, Anda mem-bash lingkungan mengandung:
Jadi kamu bisa:
Ini akan membuat:
Tapi ini diurutkan secara numerik! Jika Anda ingin pesanan asli, Anda dapat:
Jadi, Anda menampilkan vol dalam urutan yang sama seperti yang dikirimkan:
atau
untuk ditampilkan hanya dalam A :
atau bahkan:
akan dicetak ulang :
sumber
Duplicate
garis tidak berguna, mereka bisa saja dijatuhkan.