Вот для чего был разработан 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 - номер строки текущего файла. Два будут равны только во время чтения 1-го файла.
c[$1$2]++; next
: если это первый файл, сохраните первые два поля в c
массиве. Затем перейдите к следующей строке, чтобы она применялась только к 1-му файлу.
c[$1$2]>0
: блок else будет выполняться, только если это второй файл, поэтому мы проверяем, были ли уже видны поля 1 и 2 этого файла ( c[$1$2]>0
), и если они были, мы печатаем строку. В awk
, действие по умолчанию состоит в том, чтобы напечатать строку, поэтому, если значение c[$1$2]>0
равно true, строка будет напечатана.
Кроме того, поскольку вы пометили с помощью Perl:
perl -e 'open(A, "file2"); while(<A>){/.+?\|[^|]+/ && $k{$&}++};
while(<>){/.+?\|[^|]+/ && do{print if defined($k{$&})}}' file1
объяснение
Откроется первая строка file2
, прочитайте все, вплоть до 2nd |
( .+?\|[^|]+
), и сохраните это ( $&
результат последнего оператора соответствия) в %k
хэше.
Вторая строка обрабатывает file1, использует одно и то же регулярное выражение для извлечения первых двух столбцов и печатает строку, если эти столбцы определены в %k
хэше.
Оба вышеупомянутых подхода должны будут содержать 2 первых столбца файла 2 в памяти. Это не должно быть проблемой, если у вас есть только несколько сотен тысяч строк, но если это так, вы можете сделать что-то вроде
cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done
Но это будет медленнее.