
次のタブ区切り形式で生成されるレポートがあります。
UNIT TC CC PC TCP FTX FRX
HOUSE 55 65 75 85 95 105
CAR 100 200 300 400 500 600
H2 5 10 15 20 25 30
C2 10 20 30 40 50 60
次の形式に変更する必要があります。
HOUSE TC 55
HOUSE CC 65
HOUSE PC 75
HOUSE TCP 85
HOUSE FTX 95
HOUSE FRX 105
CAR TC 100
CAR CC 200
CAR PC 300
CAR TCP 400
CAR FTX 500
CAR FRX 600
等々。
SED AWK BASH などの標準ツールを使用したいと思いますが、ご提案があれば歓迎します。コードは、事前にデータを解析して連結するために既に使用している BASH スクリプトに挿入されます。エントリの数は常に同じなので、レポートは変更されません。
答え1
試す:
$ awk 'BEGIN { FS="\t" } NR==1 { split($0,header,"\t") ; next } { for(i=2;i<=NF;i++) print $1,header[i],$i }' data
HOUSE TC 55
HOUSE CC 65
HOUSE PC 75
HOUSE TCP 85
HOUSE FTX 95
HOUSE FRX 105
CAR TC 100
CAR CC 200
CAR PC 300
CAR TCP 400
CAR FTX 500
CAR FRX 600
H2 TC 5
H2 CC 10
H2 PC 15
H2 TCP 20
H2 FTX 25
H2 FRX 30
C2 TC 10
C2 CC 20
C2 PC 30
C2 TCP 40
C2 FTX 50
C2 FRX 60
ワンライナーを細かく分解すると次のようになります。
入力ファイルのフィールド区切り文字としてタブ文字を設定します。
BEGIN { FS="\t" }
最初の行 ( NR==1
) は、それをフィールドに分割し、配列に格納しますheader
。これは、すべてのフィールド $1、$2、... を for ループにコピーして格納するよりも簡単です。このnext
コマンドは、行 1 が次のコードによって処理されるのを防ぎます。これは他の行のみを対象としています。(FS
の代わりに を使用すると、"\t"
より適切になります...)
NR==1 { split($0,header,"\t") ; next }
他の各行 ( ) では、$1 とフィールド名 ( ) がプレフィックスとして付いたNR!=1
すべてのフィールド ( ) を印刷します。 $2...$NF
header[i]
{ for(i=2;i<=NF;i++) print $1,header[i],$i }
OFS=FS="\t"
ブロック内で設定すると、フィールド間でタブが使用されるBEGIN
ようになりますprint
。すべての出力行も再フォーマットする必要があるため、回答ではこれを変更しませんでした。