同じキーで列範囲を結合する

同じキーで列範囲を結合する
Input file tab separated:
A   |B   |  C | KEY  |  D|  E|  F  |G     | H | I | J   |   k |      
----|----|----|------|---|---|-----|------|---|---|-----|-----|      
word|word|word| one  |  8|  8|qw123| ""   | ""| ""| word| word|      
word|word|word| one  |  8|  8|qw234| ""   | ""| ""| word| word|      
word|word|word| one  |  8|  8|qw111| er432| ""| ""| word| word|      
word|word|word| seven|  8|  8|tr123| ""   | ""| ""| word| word|      
word|word|word| seven|  8|  8|ww000| ""   | ""| ""| word| word|      


Desired Output:                                                                     
A   |B   |  C | KEY  |D |E |F    |G    |H    |I    |J   |K   |  
----|----|----|------|--|--|-----|-----|-----|-----|----|----|
word|word|word|one   | 8| 8|qw123|qw234|qw111|er432|word|word|
word|word|word|one   | 8| 8|qw123|qw234|qw111|er432|word|word|
word|word|word|one   | 8| 8|qw123|qw234|qw111|er432|word|word|
word|word|word|seven | 8| 8|tr123|ww000|""   |""   |word|word|
word|word|word|seven | 8| 8|tr123|ww000|""   |""   |word|word|

[F〜I]列範囲を同じKEYにマージします。配列を使用せずにAWKでこれを達成できますか?キー列の値が変更されるタイミングを制御する方法は何ですか?

ベストアンサー1

配列を使用せずにAwkでこれを行う方法を理解できません。配列要素が配列になることを可能にするGawkではより便利ですが、多次元配列をエミュレートするために通常のAwkを使用することも簡単です。

デフォルトでは、入力行を覚えてからキーが変更されたら、それを出力(更新されたFIフィールドと共に)する必要があります。ファイルの最後でもこれを行う必要があります。便宜上、出力関数は必然的に2つの場所で呼び出されるので使用します。

以下は固定列番号を使用します。 1-6と11-12は標準データフィールド、4はキーフィールド、7-10はマージフィールドです。より良い名前が必要なので、ラベルと呼びます。これは良いスタイルではなく、いくつかの変数に分割する必要があるかもしれません。

awk -F '\t' '
  function show_and_reset(            i, c) {
    for (i = 1; i <= count; ++i) {
      for (c = 1; c <= 6; ++c) printf "%s\t", data[i,c]
      for (f in tags) printf "%s\t", f;
      for (c = ntags; c <= 3; ++c) printf "\t" 
      for (c = 11; c <= 12; ++c) printf "\t%s", data[i,c]
      print ""
    }
    /* Clear the holding data */
    for (f in tags) delete tags[f]
    ntags = 0;
    count = 0
  }
  /* Record one line of data */
  function record(                   c) {
    ++count;
    for (c = 1; c <= 6; ++c) data[count,c] = $c
    for (c = 11; c <= 12; ++c) data[count,c] = $c
    for (c = 6; c <= 10; ++c) 
      if ($c != "" && !tags[$c]++) ++ntags;
  }
  $4 != key { show_and_reset(); key = $4; }
            { record(); }
  END       { show_and_reset(); }
'

おすすめ記事