1

我有两个文件,我想将 file1 中的第 2 列与 file2 中的 NF 列相匹配。如果它们匹配,我想从 file2 输出整行,此外还有 file1 中的第 5 列和文件 1 中的第 5 列,最后与文件 2 中的 NF-2 列相乘。这些文件有不同的长度。

我有以下两种文件类型:

文件 1

xx  name1 1 we    freq1
xy  name2 2 wer   freq2
xz  name3 3 werf  freq3

文件2

..... value1 cv name1
..... value4 cvb name4
..... value3 cvb name3  
..... value1 vbn name5

期望的输出

..... value1 cv name1 freq1 (freq1*value1)
..... value3 cvb name3 freq3 (freq3*value3)

我曾尝试使用 awk 执行此操作。

awk 'FNR==NR { 二[$0]++; 下一个 } { for (i in two) { split(i, one); if (one[2] == $NF) print $0, one[5], $(NF-2)*one[5] } }' file1 file2 > file3

它可以工作,但是效率极低,并且在一段时间后使我的comp崩溃。这些文件每个大约有 100,000 行。也许我应该为此使用 perl 或 python?或者有没有办法读取文件2?谢谢!

4

3 回答 3

3

听起来最好的方法是将所有相关列(2 和 5)从file1哈希中读取,然后file2逐行处理。

如果哈希使用file1第 2 列作为键,那么可以简单地用最后一列的值进行索引,file2以查看其他文件中是否存在相应的值。

Then all that is necessary is to print the values from the file2 record, plus the calculated values using the data from the hash element.

This program demonstrates. The variable names are a little obscure as you don't give a meaning to the fields in your question, so all I can do is refer to file and column numbers.

I have had to output string*string instead of the actual product, because your data doesn't have numerical values.

use strict;
use warnings;
use autodie;

open my $fh1, '<', 'file1';
my %file1;
while (<$fh1>) {
  my ($f1_2, $f1_5) = (split)[1,4];
  $file1{$f1_2} = $f1_5;
}

open my $fh2, '<', 'file2';
while (<$fh2>) {
  my @f2_rec = split;
  my ($f2_nm2, $f2_n) = @f2_rec[-3,-1];
  if (my $f1_5 = $file1{$f2_n}) {
    print join(' ', @f2_rec, $f1_5, "$f1_5*$f2_nm2"), "\n";
  }
}

output

..... value1 cv name1 freq1 freq1*value1
..... value3 cvb name3 freq3 freq3*value3
于 2013-10-14T18:21:49.923 回答
3

All you need is:

awk 'NR==FNR{a[$2]=$NF;next} $NF in a{print $0, a[$NF], a[$NF] * $(NF-2)}' file1 file2

e.g.:

$ cat file1
xx  name1 1 we    3
xy  name2 2 wer   5
xz  name3 3 werf  7

$ cat file2
..... 2 cv name1
..... 4 cvb name4
..... 6 cvb name3
..... 8 vbn name5

$ awk 'NR==FNR{a[$2]=$NF;next} $NF in a{print $0, a[$NF], a[$NF] * $(NF-2)}' file1 file2
..... 2 cv name1 3 6
..... 6 cvb name3 7 42
于 2013-10-15T02:04:25.783 回答
2
perl -ane'
  BEGIN{ open($f,shift)||die$!; %h = (%h, (split)[1,4]) while <$f> }
  $fq = $h{$F[-1]} or next;
  s|$| sprintf(" %s (%s)", $fq, "$fq*$F[-3]") |e;
  print;
' file1 file2 > file3

表示为独立脚本:

#!/usr/bin/perl
use strict; use warnings;

my %frequencies;

my $frequency_file = shift @ARGV;
open my $fh, "<", $frequence_file or die "Can't open $frequency_file: $!";

while (<$fh>) {
  my (undef, $name, undef, undef, $freq) = split;
  $frequencies{$name} = $freq;
}

while (<>) {
  my @fields = split;
  my ($value, $name) = @fields[-3, -1];
  next if not exists $frequencies{$name};
  my $freq = $frequencies{$name};
  print join(" ", @fields, $freq, "($freq * $value)"), "\n";
}

输出

..... value1 cv name1 freq1 (freq1*value1)
..... value3 cvb name3   freq3 (freq3*value3)

删除双引号"$fq*$F[-3]"以进行实际乘法。

于 2013-10-14T17:38:00.483 回答