特定の用語を含む行の列の合計

特定の用語を含む行の列の合計

同じ識別子を持つすべての行列を合計するsedコマンドがあるかどうかを知りたいです。awkたとえば、私のファイルはdata.txt次のようになりますが、約1800のデータ列と約1400の行が含まれています。

ABCD:1234  1.23  0.23  0.83   0
ABCD:1234    0    1.10  0.21   0 
EFGH:5678    0    1.90  0.12  8.21
IJKL:9999    1.22  0    1.84  9.21
IJKL:9999    1.44  0   12.94   0
IJKL:9999    1.32  0   24.12   2.43

後でコマンドがどのように見えるようにしたいか:

ABCD:1234  1.23  1.33  1.04  0
EFGH:5678    0    1.90  0.12  8.21
IJKL:9999   3.98   0   38.9  11.64

awkこれがsed(私は生物学者であり、まだUnixの基礎を学んでいます)で動作するかどうかわかりません。どんな助けでも大変感謝します。

答え1

awk入力ファイルまたは結果テーブル全体をメモリに保存しないスクリプト:

FNR == 1   { for(i = 1; i <= NF; i++) a[i] = $i;  next }
$1 == a[1] { for(i = 2; i <= NF; i++) a[i] += $i; next }
{
    printf "%s", a[1]; a[1] = $1;
    for(i = 2; i <= NF; i++) { printf "\t%s", a[i]; a[i] = $i };
    printf "\n";
}
END {
    printf "%s", a[1];
    for(i = 2; i <= NF; i++) printf "\t%s", a[i];
    printf "\n";
}

実行してください:

awk -f script.awk data.txt

結果:

ABCD:1234       1.23    1.33    1.04    0
EFGH:5678       0       1.90    0.12    8.21
IJKL:9999       3.98    0       38.9    11.64

注:実際には動作しますsedが、まもなくそうすることはありません。バラよりここ理由を調べてください。

答え2

代替ソリューションperl

$ perl -nale '
if(!$seen{$F[0]}++)
{
    print join "\t", @a if @a;
    @a = @F[0..$#F];
}
else
{
    $a[$_] += $F[$_] foreach(1..$#F);
}
print join "\t", @a if eof;
' data.txt 
ABCD:1234   1.23    1.33    1.04    0
EFGH:5678   0       1.90    0.12    8.21
IJKL:9999   3.98    0       38.9    11.64
  • -a入力行をスペースに分割して配列@Fに保存します。
  • 行の最初のフィールドはハッシュ変数のキーとして使用されます%seen。キーが見つからない場合は、配列@aの内容が印刷され(空でない場合)、新しい行のフィールドが配列に割り当てられます。
  • キーがすでに存在する場合は、配列の内容(2番目のフィールドから最後まで)を現在の行の内容に追加します。
  • @a最後の項目を処理するには、ファイルの終わりに達したら配列の内容を再印刷します。


重複質問の場合:最初の列に同じ項目がある場合は、Linuxですべての列を別々に追加します。

$ perl -nale '
if(!$seen{$F[0]}++)
{
    print join "\t", @a if @a;
    @a = @F[0..$#F];
}
else
{
    $a[$_] += $F[$_] foreach(1..$#F);
}
print join "\t", @a if eof;
' filename.txt 
AC1481523   6   6   6   6
AC1481676   6   5   6   8


配列ハッシュを構築し、最後にハッシュを印刷するソリューション:

$ perl -nale '
if($h{$F[0]})
{
    $h{$F[0]}[$_] += $F[$_] foreach (1..$#F)
}
else
{
    $h{$F[0]} = [@F]
}
END { print join "\t",@{$h{$_}} foreach sort keys %h }
' data.txt
ABCD:1234   1.23    1.33    1.04    0
EFGH:5678   0       1.90    0.12    8.21
IJKL:9999   3.98    0       38.9    11.64

関連情報