Inilah yang dirancang untuk awk:
$ awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' file2 file1
abc|123|BNY|apple|
cab|234|cyx|orange|
Penjelasan
-F'|': mengatur pemisah bidang ke |.
NR==FNR: NR adalah nomor baris input saat ini dan FNR nomor baris file saat ini. Keduanya akan sama hanya saat file 1 sedang dibaca.
c[$1$2]++; next: jika ini adalah file ke-1, simpan kedua bidang ke-1 dalam carray. Kemudian, lewati ke baris berikutnya sehingga ini hanya diterapkan pada file ke-1.
c[$1$2]>0: blok else hanya akan dieksekusi jika ini adalah file kedua jadi kami memeriksa apakah bidang 1 dan 2 dari file ini sudah terlihat ( c[$1$2]>0) dan jika sudah, kami mencetak baris. Dalam awk, tindakan standar adalah mencetak garis jadi jika c[$1$2]>0benar, garis akan dicetak.
Atau, karena Anda ditandai dengan Perl:
perl -e 'open(A, "file2"); while(<A>){/.+?\|[^|]+/ && $k{$&}++};
while(<>){/.+?\|[^|]+/ && do{print if defined($k{$&})}}' file1
Penjelasan
Baris pertama akan terbuka file2, membaca semuanya hingga ke-2 |( .+?\|[^|]+) dan menyimpannya (itu $&adalah hasil dari operator pertandingan terakhir) di %khash.
Baris kedua memproses file1, menggunakan regex yang sama untuk mengekstrak dua kolom pertama dan mencetak baris jika kolom tersebut didefinisikan dalam %khash.
Kedua pendekatan di atas perlu menahan 2 kolom pertama file2 dalam memori. Itu seharusnya tidak menjadi masalah jika Anda hanya memiliki beberapa ratus ribu baris tetapi jika ya, Anda bisa melakukan sesuatu seperti
cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done
Tapi itu akan lebih lambat.