Вы можете сделать это в Awk за один проход по файлам, если в списке аргументов вы сначала указали справочный файл:
awk 'FNR == NR { name[$1] = 0; }
FNR != NR { for (i in name) if ($0 ~ i && name[i]++ == 0) { print $0; break; } }' \
reference.txt file.txt
При вводе сэмплов это дает требуемый вывод.
Это довольно стандартная техника в Awk. Вы читаете первый файл, используя условие FNR == NR
(номер строки файла равен общему номеру строки; значение true только для строк в первом файле) и сохраняете соответствующую информацию для последующего использования. Часто люди используют next
в первой строке; оно работает. Это означает, что они могут избежать
условие FNR != NR
- мне нравится это для симметрии.
При обработке второго и последующих файлов проверьте, совпадает ли каждое из имен, считанных из первого файла, с линией, а имя не было напечатано ранее, печатая строку, если она не была обработана. Перерыв не позволяет проверять другие имена, если текущее имя совпадает.
Именно так многие люди будут писать команду; это тоже работает.
awk 'FNR == NR { name[$1] = 0; next }
{ for (i in name) if ($0 ~ i && name[i]++ == 0) { print $0; break; } }' \
reference.txt file.txt
Обе версии кода здесь ищут имя в любом месте строки; если вы строго хотите соответствовать $1
второго (или последующих) файлов, вы можете изменить условия (в действительности, упростить их). И karakfa показывает удаление совпадений при их совпадении (вместо увеличения счетчика), что лучше для производительности, поскольку вам не нужно продолжать сопоставлять то, что больше не актуально , Тем не менее, код, показанный здесь, было бы проще адаптировать для отображения второй, третьей или последней записи для данного имени (обработка второй или третьей включает изменение от 0 до 1 или 2; обработка «последнего» требует более существенных изменений).