cat file_1
my colour is red
my rose is red
my colour is blue
my rose id blue
cat file_2
red
blue
cat output_file should be
my colour is red
my colour is blue
здесь я использую
cat file_2 | while read line;do cat file_1 | grep "$line" | head -1;done
здесь я пытаюсь получить самую верхнюю строку, содержащую , pattern "red" and "blue"
которая присутствует вfile_2
есть ли другой способ сделать, as fast as possible
пока цикл занимает время
решение1
Вы можете использовать while
конструкцию для перебора шаблонов from file2
, а затем использовать -m 1
with grep
для остановки после первого совпадения on file1
:
while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
-F
воспринимает шаблон буквально-m 1
заставляетgrep
выйти после первого матча
Циклы оболочки обычно неэффективны, но, учитывая небольшой список шаблонов, в данном случае их можно использовать.
Более быстрая альтернатива, xargs
:
xargs -a file2 -n1 -P2 -I'{}' grep -Fm1 {} file1
Используйте больше параллельных процессов ( -P
) для большего количества шаблонов.
Пример:
% while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
my colour is red
my colour is blue
% xargs -a file2 -n1 -P2 -I'{}' grep -Fm1 {} file1
my colour is blue
my colour is red
решение2
Чтобы напечатать первую строку из file_1, которая соответствует строке в file_2:
$ awk 'FNR==NR{a[$0];next} {for (line in a) if ($0~line) {print; delete a[line]}}' file_2 file_1
my colour is red
my colour is blue
При таком подходе каждый файл читается только один раз.
Как это работает
FNR==NR{a[$0];next}
Это сохраняет каждую строку в file_2 как ключ в ассоциативном массиве
a
.for (line in a) if ($0~line) {print; delete a[line]}
Для каждой строки в file_1 мы проверяем, соответствует ли она ключу в array
a
. Если соответствует, мы печатаем строку и удаляем ключ.