Sue
Sue

Reputation: 21

Compare two files and print N lines after the matching word

I need to search a name from File1 against File2. If the matching name is found, I need to print it together with three lines after it.

— File1 —

Name1
Name2
Name3

— File2 —

Topic1 ....description...
lineA
lineB
lineC
Name1 ....description...
lineA
lineB
lineC
Name3 ....description...
lineA
lineB
lineC
Topic2 ....description...
lineA
lineB
lineC
Topic3 ....description...
lineA
lineB
lineC

— Expected result —

Name1 ....description...
lineA
lineB
lineC
Name3 ....description...
lineA
lineB
lineC

My problem now is I don't know how to combine these two commands. Perhaps someone can suggest a Perl script to run these flow?

Upvotes: 2

Views: 1207

Answers (3)

Allen Supynuk
Allen Supynuk

Reputation: 144

I would have used xargs:

cat File1 | xargs -I NAME grep -A3 NAME File2

The canonical way to look for a NAME in File2 and show the matching line and the three lines after it is:

grep -A3 NAME File2

The way to generate such a command for each line of File 1, using the line as NAME is:

cat File1 | xargs -I NAME <COMMAND with NAME in it>

Upvotes: 0

Borodin
Borodin

Reputation: 126742

This should work for you. It reads all of the names from File1 into a hash, so that the values from File2 can be quickly checked.

File2 is read line by line, and the first field checked against the hash to see if it is one of the wanted names. If so, then the current line and the three following lines are printed.

use strict;
use warnings;
use 5.010;
use autodie;

my %names;

open my $fh, '<', 'File1';

while ( <$fh> ) {
  chomp;
  ++$names{$_};
}

open $fh, '<', 'File2';

while ( <$fh> ) {
  my ($name) = split;
  if ( $names{$name} ) {
    print;
    print scalar <$fh> for 1 .. 3;
  }
}

output

Name1 ....description...
lineA
lineB
lineC
Name3 ....description...
lineA
lineB
lineC

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 247012

You can pass grep a file containing patterns (-f option), so

$ grep -F -f file1 -A3 file2
Name1 ....description...
lineA
lineB
lineC
Name3 ....description...
lineA
lineB
lineC

Using -F to indicate the patterns are fixed strings, not regular expressions.

Upvotes: 1

Related Questions