Datenzeile(n) in eine einzelne Spalte verschieben und dabei die Zeilenüberschrift(en) beibehalten

Datenzeile(n) in eine einzelne Spalte verschieben und dabei die Zeilenüberschrift(en) beibehalten

Ich habe Berichte, die im folgenden tabulatorgetrennten Format generiert werden:

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

Ich muss sie in das folgende Format ändern:

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

Und so weiter.

Ich würde gerne Standardtools wie SED AWK BASH verwenden, aber Vorschläge sind willkommen. Der Code wird in ein BASH-Skript eingefügt, das ich bereits verwende, um die Daten im Voraus zu analysieren und zu verketten. Die Anzahl der Einträge bleibt immer gleich, die Berichte ändern sich nicht.

Antwort1

Versuchen:

$ 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

Der in Stücke zerlegte Oneliner:

Tabulatorzeichen als Feldtrennzeichen für Eingabedateien festlegen:

BEGIN { FS="\t" }

Wenn die erste Zeile ( NR==1) in Felder aufgeteilt und im Array gespeichert wird header. Das ist einfacher, als alle Felder $1, $2, ... in einer for-Schleife zu kopieren und zu speichern. Der nextBefehl verhindert auch, dass Zeile 1 vom folgenden Code verarbeitet wird, der nur für die anderen Zeilen gilt. ( FSstatt "\t"wäre konsequenter gewesen...)

NR==1 { split($0,header,"\t") ; next }

Drucken Sie für jede zweite Zeile ( NR!=1) alle Felder ( $2...$NF) mit dem Präfix $1 und dem Feldnamen ( header[i]) aus.

{ for(i=2;i<=NF;i++) print $1,header[i],$i }

Durch die Einstellung OFS=FS="\t"im BEGINBlock wird printein Tabulator zwischen den Feldern verwendet. Ich habe dies in der Antwort nicht geändert, da auch alle Ausgabezeilen neu formatiert werden müssten.

verwandte Informationen