我有两个文件
$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 '!/--/'
但我想知道是否有更优雅的解决方案。当文件很大时,当前的解决方案需要很长时间
答案 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