根据当前文件的内容从awk搜索/读取另一个文件,这可能吗?
我正在使用(GNU)awk处理一个巨大的文件(其他可用的工具是:Linux shell工具,Perl的某些旧版本(> 5.0),但无法安装模块)。
我的问题:如果某个field1,field2,field3包含X,Y,Z,我必须在另一目录中的一行中包含field4和field5的文件中搜索文件,然后将找到的文件中的一些数据插入当前输出。
例如。:
实际文件行:
f1 f2 f3 f4 f5 X Y Z A B
现在我需要搜索另一个文件(在另一个目录中),其中包含例如
f1 f2 f3 f4 A U B W
然后从原始文件写入STDOUT$ 0,并从找到的文件写入f2和f3,然后处理原始文件的下一行。
是否可以用" awk"做到这一点?
解决方案
这似乎适用于我根据示例设置的一些测试文件。但是,以这种方式(与grep插入)一起使用perl可能会严重损害性能,但是...
## perl code to do some dirty work
for my $line (`grep 'X Y Z' myhugefile`) {
chomp $line;
my ($a, $b, $c, $d, $e) = split(/ /,$line);
my $cmd = 'grep -P "' . $d . ' .+? ' . $e .'" otherfile';
for my $from_otherfile (`$cmd`) {
chomp $from_otherfile;
my ($oa, $ob, $oc, $od) = split(/ /,$from_otherfile);
print "$a $ob $oc\n";
}
}
编辑:使用tsee的解决方案(以上),这是经过深思熟虑的。
首先,我要说问题描述并没有那么大的帮助。下次,请更加具体:我们可能会错过更好的解决方案。
因此,根据描述,我了解我们有两个文件,其中包含以空格分隔的数据。在第一个文件中,我们想将前三列与某种搜索模式进行匹配。如果找到,则要在另一个文件中查找所有行,其中包含第一个文件中匹配行的第四和第五列。从这些行中,我们需要提取第二列和第三列,然后打印第一个文件的第一列以及第二个文件的第二列和第三列。好的,这里是:
#!/usr/bin/env perl -nwa
use strict;
use File::Find 'find';
my @search = qw(X Y Z);
# if you know in advance that the otherfile isn't
# huge, you can cache it in memory as an optimization.
# with any more columns, you want a loop here:
if ($F[0] eq $search[0]
and $F[1] eq $search[1]
and $F[2] eq $search[2])
{
my @files;
find(sub {
return if not -f $_;
# verbatim search for the columns in the file name.
# I'm still not sure what your file-search criteria are, though.
push @files, $File::Find::name if /\Q$F[3]\E/ and /\Q$F[4]\E/;
# alternatively search for the combination:
#push @files, $File::Find::name if /\Q$F[3]\E.*\Q$F[4]\E/;
# or search *all* files in the search path?
#push @files, $File::Find::name;
}, '/search/path'
)
foreach my $file (@files) {
open my $fh, '<', $file or die "Can't open file '$file': $!";
while (defined($_ = <$fh>)) {
chomp;
# order of fields doesn't matter per your requirement.
my @cols = split ' ', $_;
my %seen = map {($_=>1)} @cols;
if ($seen{$F[3]} and $seen{$F[4]}) {
print join(' ', $F[0], @cols[1,2]), "\n";
}
}
close $fh;
}
} # end if matching line
与另一个包含大量系统调用的海报解决方案不同,此解决方案完全不会退回到Shell上,因此应该足够快。
这是使我首先从awk转到perl的工作类型。如果要完成此任务,实际上可能会发现创建外壳脚本更容易,该外壳脚本会创建要查询的awk脚本,然后在单独的步骤中进行更新。
(我写了这样的野兽来读取/更新Windows-ini风格的文件,这很丑陋。我希望我可以使用perl。)
我经常看到"我不能使用任何Perl模块"的限制,并且当这不是家庭作业问题时,通常只是由于缺乏信息。是的,即使我们可以使用CPAN,也包含有关如何在没有root特权的情况下本地安装CPAN模块的说明。另一种选择是仅获取CPAN模块的源代码并将其粘贴到程序中。
如果还有其他未说明的限制(例如,磁盘空间不足,无法安装(过多)添加文件),则所有这些都无济于事。

