根据当前文件的内容从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模块的源代码并将其粘贴到程序中。
如果还有其他未说明的限制(例如,磁盘空间不足,无法安装(过多)添加文件),则所有这些都无济于事。