AWKを使用して行がほとんどない列に変換[重複]

AWKを使用して行がほとんどない列に変換[重複]

次の内容を含むテキストファイルがあります。

タイトル1 A1
タイトル3 A3
タイトル4 A4
タイトル5 A5

タイトル1 B1
タイトル2 B2
タイトル5 B5

タイトル1 C1
タイトル2 C2
タイトル4 C4
タイトル5 C5

タイトル 1 D1
タイトル 2 D2
タイトル 3 D3

私は次の出力が欲しい:

title1      title2       title3        title4      title5  
  A1                        A3           A4          A5  
  B1           B2                                    B5  
  C1           C2                        C4          C5  
  D1           D2           D3                        

AWKを使ってコードを書く方法を教えてください。

よろしくお願いします!

答え1

空白(または「:」)だけで区切られるようにデータを変更できる場合は、次のawkプログラムがこれを実行できます。レイアウトを完璧にするために調整する必要があるかもしれません。

BEGIN { i = 1; }
$1 != "" { C[$1] = $1; X[$1,i] = $2 ; next; }
{ i++; }
END {
    asort(C);
    for ( k in C ) printf "  %8s\t", C[k];
    printf "\n";
    for ( j = 1; j <= i; j++ ) {
        for ( k in C ) printf "%8s\t",X[C[k],j];
        printf "\n";
    }
}

答え2

awk -f  transpose_rows_to_cols.awk /tmp/1
title1  title2  title3  title4  title5
A1      A3  A4  A5
B1  B2          B5
C1  C2      C4  C5
D1  D2  D3      

PS。端末でフォーマットするだけです。

スクリプト -

#!/usr/bin/awk -f
BEGIN {
    printf("title1\ttitle2\ttitle3\ttitle4\ttitle5\n");
    a["title1"] = a["title2"]= a["title3"]= a["title4"]= a["title5"] = ""
}
{
    if ($0 !~ /^$/) {
        if ($0 ~ /:/)  {FS=":"; $0=$0} else {FS=" "; $0=$0}
        a[$1]=$2
    } else {
        printf("%s\t%s\t%s\t%s\t%s\n", a["title1"], a["title2"], a["title3"], a["title4"], a["title5"])
        a["title1"] = a["title2"]= a["title3"]= a["title4"]= a["title5"] = ""
    }
}
END{
        printf("%s\t%s\t%s\t%s\t%s\n", a["title1"], a["title2"], a["title3"], a["title4"], a["title5"])
}

答え3

この回答は以下に基づいています。Ralph Rehnquistの回答、しかし

  1. 列は、ヘッダーごとのアルファベット順ではなく、ユーザーが指定した順序で出力する必要があるとします。
  2. データ値は複数の単語が許可されます。

Ralphの答えと同様に、タイトルがコロンではなく空白でデータから分離されているとします。

目標1を達成するには、入力が必要な順序ですべてのヘッダー(付随するデータなし)を含むセクションから始める必要があります。

BEGIN { i = 0; j= 0; }
$1 != "" { if (i==0) C[++j] = $1; else { label = $1; $1 = ""; X[label,i] = $0; } next; }
{ i++; }
END {
    for ( k in C ) printf "  %8s\t", C[k];
    printf "\n";
    for ( j = 1; j <= i; j++ ) {
        for ( k in C ) printf "%8s\t", X[C[k],j];
        printf "\n";
    }
}

はでi初期化され0、そのi==0ケースは特別に処理されます。ヘッダーだけがキャプチャされ(これが必要な唯一のものなので)、ヘッダーは値ではなくC増分整数()で索引付けされた配列に格納されます。jヘッダ自体の。それ以外の場合はデータをキャプチャします。  $1 = "";行の最初のフィールドを削除し、他のすべてのフィールドを$0リンクして再構築します。 (これにより、フィールド間に複数のスペースが失われます。これはいくつかの操作で変更される可能性があります。)データ配列のインデックスとして使用できるように、値を変数に保存します$1labelX

たとえば、次の入力は次のようになります。

name
address
phone
height
weight

name John Lennon
phone 123
height 6' 1"
weight 180

name Sir Paul M.
address Liverpool
weight 175

name George
address 42                 Main St.
height 71"
weight 185 lbs

name Ringo Starr
address Penny Lane
phone 456 789

次の出力を生成します。

      name         address           phone          height          weight
 John Lennon                         123           6' 1"             180
 Sir Paul M.     Liverpool                                           175
  George         42 Main St.                         71"         185 lbs
 Ringo Starr     Penny Lane      456 789

値が15文字以上の場合、対応する列はオフになります。これは改善することができます。

関連情報