如何从引用第一个文件的另一个文件中检索一组两行?

时间:2012-04-13 17:47:38

标签: perl file unix command-line

我有两个文件

$cat file 1
Index1 annotation1
abcd
Index2 annotation2
efgh
Index3 annotation3
hijk
Index4 annotation4
lmno
Index5 annotation5
pqrs
…
$cat file2
Index1
Index3
Index5

我想得到的是文件1中的行列表以及后面检索的每行后面的行。

Index1 annotation1
abcd
Index3 annotation3
hijk
Index5 annotation5
pqrs

我目前的解决方案是使用grep及其'file'标志 grep -A 1 --file="file2" file1 | awk '!/--/'

但我想知道是否有更优雅的解决方案。当文件很大时,当前的解决方案需要很长时间

2 个答案:

答案 0 :(得分:2)

#!/usr/bin/env perl

use strict; use warnings;
use autodie;

my %to_index;

my ($annotations_file, $index_file) = @ARGV;

open my $index, '<', $index_file;

while (my $line = <$index>) {
    next unless $line =~ /\S/;
    chomp $line;
    $to_index{ $line } = undef;
}

close $index;

open my $annotations, '<', $annotations_file;

while (my $line = <$annotations>) {
    next unless $line =~ /\S/;
    my ($keyword) = ($line =~ /^(\S+)/);
    if (exists $to_index{ $keyword }) {
        print $line;
        print scalar <$annotations>;
    }
}

close $annotations;

答案 1 :(得分:2)

我建议通过file1来读取每个标签在文件中出现的位置的索引。可以从file2读取所需数据的标签,并查阅索引以查看相应信息的读取位置。

该程序显示原理。目前尚不清楚如何区分标签和其他测试。我假设它们都以Index开头,这可能是错误的,但如果您需要帮助将其调整为真实数据,请再次询问。

use strict;
use warnings;

@ARGV = qw/ file1.txt file2.txt / unless @ARGV;
my ($file1, $file2) = @ARGV;

my %index;

open my $f1, '<', $file1 or die qq(Unable to open "$file1": $!);
my $pos = tell $f1;
while (<$f1>) {
  $index{$1} = $pos if /^(Index\S+)/;
  $pos = tell $f1;
}

open my $f2, '<', $file2 or die qq(Unable to open "$file2": $!);
while (<$f2>) {
  next unless /^(Index\S+)/ and defined($pos = $index{$1});
  seek $f1, $pos, 0;
  print scalar <$f1>, scalar <$f1>;
}

<强>输出

Index1 annotation1
abcd
Index3 annotation3
hijk
Index5 annotation5
pqrs