1
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

here i am using

cat file_2 | while read line;do cat file_1 | grep "$line" | head -1;done

here i am trying to get the top most line containing the pattern "red" and "blue" which is present in the file_2

is there any other way to do , as fast as possible, while loop is taking time

prince 987
  • 74
  • 1
  • 7

2 Answers2

4

You can use a while construct to loop over the patterns from file2 and then use -m 1 with grep to stop after first match on file1:

while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
  • -F treats the pattern literally
  • -m 1 makes grep to exit after first match

Shell loops are usually not efficient, but given the pattern list is small it is usable in this case.

Faster alternative, xargs:

xargs -a file2 -n1 -P2 -I'{}' grep -Fm1 {} file1

Use more parallel processes (-P) for more patterns.

Example:

% 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
heemayl
  • 56,300
2

To print the first line from file_1 that matches a line in 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

This approach reads through each file just once.

How it works

  • FNR==NR{a[$0];next}

    This saves every line in file_2 as a key in associative array a.

  • for (line in a) if ($0~line) {print; delete a[line]}

    For every line in file_1, we check to see if it matches a key in array a. If it does, we print the line and delete the key.

John1024
  • 74,655