Data pivot con awk

Estoy tratando de pivotar un file usando awk. Este es un ejemplo de mi file de input:

VarName;TimeString;VarValue;Validity;Time_ms A;23.11.201215:03:53;1;1;41236627696,7593 C;23.11.201215:03:53;2;1;41236627696,7593 D;23.11.201215:03:53;3;1;41236627696,7593 A;23.11.201215:04:53;31;1;41236628391,2037 B;23.11.201215:04:53;12;1;41236628391,2037 C;23.11.201215:04:53;1;1;41236628391,2037 D;23.11.201215:05:53;8;1;41236629097,2222 B;23.11.201215:05:53;7;1;41236629097,2222 C;23.11.201215:05:53;15;1;41236629097,2222 

Y este es mi resultado deseado:

 TimeString;Time_ms;A;B;C;D 23.11.201215:03:53;41236627696,7593;1;;2;3 23.11.201215:04:53;41236628391,2037;31;12;1; 23.11.201215:05:53;41236629097,2222;;7;15;8 

¿Cuál es la mejor forma de get este resultado?

Resuelto usando el script escrito por @steve

Aquí hay una forma de usar gawk . Correr como:

 awk -f script.awk file 

Contenido de script.awk :

 BEGIN { FS=OFS=";" } NR==1 { r = $2 FS $5 next } { !x[$1] a[$2,$5][$1]=$3 } END { m = asorti(x,y) for (k=1;k<=m;k++) { r = r FS y[k] } print r n = asorti(a,b) for (i=1;i<=n;i++) { for (j=1;j<=m;j++) { for (k in a[b[i]]) { if (k == y[j]) { var = a[b[i]][k] } } line = line FS var var = "" } sub(SUBSEP, FS, b[i]) print b[i] line line = "" } } 

Alternativamente, aquí está el único trazador de líneas:

 awk 'BEGIN { FS=OFS=";" } NR==1 { r = $2 FS $5; next } { !x[$1]; a[$2,$5][$1]=$3 } END { m = asorti(x,y); for (k=1;k<=m;k++) { r = r FS y[k] } print r; n = asorti(a,b); for (i=1;i<=n;i++) { for (j=1;j<=m;j++) { for (k in a[b[i]]) { if (k == y[j]) { var = a[b[i]][k] } } line = line FS var; var = "" } sub(SUBSEP, FS, b[i]); print b[i] line; line = "" } }' file 

Resultados:

 TimeString;Time_ms;A;B;C;D 23.11.201215:03:53;41236627696,7593;1;;2;3 23.11.201215:04:53;41236628391,2037;31;12;1; 23.11.201215:05:53;41236629097,2222;;7;15;8 


Primero debe ejecutar dos2unix en su file. es decir:

 dos2unix Flussi0.csv 

Alternativamente, cambie el separador de loggings a \r\n para que awk sepa a qué se parece una nueva línea de Windows. Puedes hacer esto en el bloque BEGIN :

 BEGIN { FS=OFS=";" RS="\r\n" } 

Resultados con el file de input publicado en los comentarios a continuación:

 "TimeString";"Time_ms";"FIT01";"FIT02";"FIT03";"FIT04";"FIT05";"FIT06" "22.06.2012 09:31:33";41082396909,7222;1,157408E-02;5,787041E-03;2,507718E-02;2,89352E-03;2,314816E-02;5,787035E-04 "22.06.2012 09:32:34";41082397615,7407;1,157408E-02;5,787041E-03;2,314816E-02;2,89352E-03;2,713479E-02;5,787035E-04 "22.06.2012 09:33:35";41082398321,7593;1,157408E-02;5,787041E-03;2,314816E-02;2,89352E-03;2,314816E-02;5,787035E-04 "22.06.2012 09:34:35";41082399016,2037;1,157408E-02;5,787041E-03;2,314816E-02;2,89352E-03;2,535274E-02;5,787035E-04 "22.06.2012 09:35:36";41082399722,2222;;;;;2,314816E-02; 

¿La mejor manera? No lo sé. Aquí hay una manera. Supuse que el código realmente no necesitaba mirar la línea de encabezado de los datos de input, y podría codificar TimeString;Time_ms; .

 (line > /dev/null; sort) < input_file > tmp0 # Discard the header line; sort the data. # Here lies the basic pivot: awk -F";" ' { print $1 > "tmp1" print $2 > "tmp2" print $5 > "tmp5" }' tmp0 echo "TimeString;Time_ms;\c" tr "\n" ";" < tmp1; echo tr "\n" ";" < tmp2; echo tr "\n" ";" < tmp5; echo 

Esto terminará cada línea de la salida con un punto y coma ( ; ). No estaba claro si querías eso. Si no lo quieres, probablemente puedas encontrar la manera de eliminarlo.