5

N個の列を持つ2つのファイルがあります

ファイル1:

A   1   2    3  .......  Na1
B   2   3    4  .......  Nb1

File2:

A   2   2    4  .......  Na2
B   1   3    4  .......  Nb2

File1の最初の列の値がFile2の最初の列から減算され、次のように列Nまでこのように出力される出力が必要です。

A  -1   0    -1  ........ (Na1-Na2)
B   1   0     0  ........ (Nb1-Nb2)

これを行う方法は、AWK、またはLinux環境でのPerlスクリプトですか?

4

6 に答える 6

2

これはすでに回答済みですが、ワンライナーを追加します。を使用してpaste、ファイルを連結し、awk以下を減算します。

paste file{1,2} | awk '{for (i=1;i<=NF/2;i++) printf "%s ", ($i==$i+0)?$i-$(i+NF/2):$i; print ""}'

検証:

$ cat file1
A   1   2    3   4  5
B   2   3    4   5  6

$ cat file2
A   2   2    4 10 12 
B   1   3    4  3 5

$ paste file{1,2} | awk '{for (i=1;i<=NF/2;i++) printf "%s ", ($i==$i+0)?$i-$(i+NF/2):$i; print ""}'
A -1 0 -1 -6 -7 
B 1 0 0 2 1

両方のファイルに同じ数の列が必要です。数値以外の列は同じ位置にある必要があります。数値でない場合は最初のファイルの値を出力し、そうでない場合は差を出力します。

于 2013-02-24T08:29:24.107 に答える
2

試す:

awk '{split($0,S); getline<f; for(i=2; i<=NF; i++) $i-=S[i]}1' OFS='\t' f=file1 file2
于 2013-02-24T09:24:31.430 に答える
2

これがを使用する1つの方法GNU awkです。次のように実行します:

awk -f script.awk File2 File1 | rev | column -t | rev

内容script.awk

FNR==NR {
    for(i=2;i<=NF;i++) {
        a[$1][i]=$i
    }
    next
}

{
    for(j=2;j<=NF;j++) {
        $j-=a[$1][j]
    }
}1

または、これがワンライナーです。

awk 'FNR==NR { for(i=2;i<=NF;i++) a[$1][i]=$i; next } { for(j=2;j<=NF;j++) $j-=a[$1][j] }1' File2 File1 | rev | column -t | rev

結果:

A  -1  0  -1
B   1  0   0
于 2013-02-24T13:07:58.043 に答える
2
awk 'FNR==NR{for(i=2;i<=NF;i++)a[FNR"-"i]=$i;next}{printf "\n"$1" ";for(i=2;i<=NF;i++){printf $i-a[FNR"-"i]" "}}' file1 file2
> cat file1
A   1   2    3
B   2   3    4
> cat file2
A   2   2    4
B   1   3    4
> awk 'FNR==NR{for(i=2;i<=NF;i++)a[FNR"-"i]=$i;next}{printf "\n"$1" ";for(i=2;i<=NF;i++){printf $i-a[FNR"-"i]" "}}' file1 file2 
A 1 0 1 
B -1 0 0 
>

または、これをファイルに入れます

#!/usr/bin/awk
FNR==NR{
   for(i=2;i<=NF;i++)
   a[FNR"-"i]=$i;next
     }
   {
    printf "\n"$1" ";
    for(i=2;i<=NF;i++)
    {
     printf $i-a[FNR"-"i]" "
    }
   }

次のように実行します。

awk -f file.awk file1 file2
于 2013-02-25T09:20:18.530 に答える
1

このようなもの:

use strict;
use warnings;

my (@fh, @v);
for (@ARGV) {
  open (my $handle, "<", $_) or die ("$!: $_");
  push @fh, $handle;
}
while (@v = map { [split ' ', <$_> ] } @fh and defined shift @{$v[0]}) {
  print join(" ", (shift @{$v[1]}, map { $_ - shift(@{$v[1]}) } @{$v[0]})), "\n";
}
close $_ for (@fh);

走る:

 perl script.pl input1 input2
于 2013-02-24T07:22:28.543 に答える
1

おそらくこのようなものですか?現在、手元にあるPCがないため、このコードをテストすることはできません。

このプログラムは、コマンドラインのパラメーターとして2つのファイルの名前を想定し、結果をに出力しますSTDOUT

use strict;
use warnings;
use autodie;

my @fh;
for my $filename (@ARGV) {
  open my $fh, '<', $filename;
  push @fh, $fh;
}

until (grep eof $_, @fh) {
  my @records;
  for my $fh (@fh) {
    my $line = <$fh>;
    chomp $line;
    push @records, [ split ' ', $line ];
  }

  $records[0][$_] -= $records[1][$_] for 1 .. $#{$records[0]};
  print "@{$records[0]}\n";
}
于 2013-02-24T07:25:45.043 に答える