Ось що було розроблено для awk:
$ awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' file2 file1
abc|123|BNY|apple|
cab|234|cyx|orange|
Пояснення
-F'|': встановлює роздільник поля на |.
NR==FNR: NR - номер поточного вхідного рядка, а FNR - номер рядка поточного файлу. Два будуть рівні лише під час читання першого файлу.
c[$1$2]++; next: якщо це перший файл, збережіть перші 1 поля в cмасиві. Потім перейдіть до наступного рядка, щоб це застосовано лише до 1-го файлу.
c[$1$2]>0: блок else буде виконаний лише у випадку, якщо це другий файл, тому ми перевіримо, чи вже були помічені поля 1 та 2 цього файлу ( c[$1$2]>0), і чи були вони, друкуємо рядок. У awk, дією за замовчуванням є друк рядка, тому, якщо c[$1$2]>0це правда, рядок буде надруковано.
Крім того, оскільки ви позначили Perl:
perl -e 'open(A, "file2"); while(<A>){/.+?\|[^|]+/ && $k{$&}++};
while(<>){/.+?\|[^|]+/ && do{print if defined($k{$&})}}' file1
Пояснення
Перший рядок відкриється file2, прочитайте все до 2-го |( .+?\|[^|]+) і збережіть це ( $&результат результату оператора останньої відповідності) у %kхеші.
Другий рядок обробляє file1, використовує той же регулярний вираз для вилучення перших двох стовпців і друкує рядок, якщо ці стовпці визначені в %kхеші.
Обидва вищевказані підходи потребують збереження 2 перших стовпців файлу2 в пам'яті. Це не повинно бути проблемою, якщо у вас є лише кілька сотень тисяч рядків, але якщо це так, ви можете зробити щось подібне
cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done
Але це буде повільніше.