Ось що було розроблено для 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
Але це буде повільніше.