awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}' file
salida
$ more file
0 1 2
3 4 5
6 7 8
9 10 11
$ ./shell.sh
0 3 6 9
1 4 7 10
2 5 8 11
Rendimiento frente a la solución Perl de Jonathan en un archivo de 10000 líneas
$ head -5 file
1 0 1 2
2 3 4 5
3 6 7 8
4 9 10 11
1 0 1 2
$ wc -l < file
10000
$ time perl test.pl file >/dev/null
real 0m0.480s
user 0m0.442s
sys 0m0.026s
$ time awk -f test.awk file >/dev/null
real 0m0.382s
user 0m0.367s
sys 0m0.011s
$ time perl test.pl file >/dev/null
real 0m0.481s
user 0m0.431s
sys 0m0.022s
$ time awk -f test.awk file >/dev/null
real 0m0.390s
user 0m0.370s
sys 0m0.010s
EDITAR por Ed Morton (@ ghostdog74 no dude en eliminarlo si no lo aprueba).
Quizás esta versión con algunos nombres de variables más explícitos ayude a responder algunas de las preguntas a continuación y, en general, aclare lo que está haciendo el script. También usa pestañas como separador que el OP había solicitado originalmente para manejar campos vacíos y, casualmente, embellece un poco la salida para este caso particular.
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
for (rowNr=1;rowNr<=NF;rowNr++) {
cell[rowNr,NR] = $rowNr
}
maxRows = (NF > maxRows ? NF : maxRows)
maxCols = NR
}
END {
for (rowNr=1;rowNr<=maxRows;rowNr++) {
for (colNr=1;colNr<=maxCols;colNr++) {
printf "%s%s", cell[rowNr,colNr], (colNr < maxCols ? OFS : ORS)
}
}
}
$ awk -f tst.awk file
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
Las soluciones anteriores funcionarán en cualquier awk (excepto el awk antiguo y roto, por supuesto, hay YMMV).
Sin embargo, las soluciones anteriores leen todo el archivo en la memoria; si los archivos de entrada son demasiado grandes para eso, puede hacer esto:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ printf "%s%s", (FNR>1 ? OFS : ""), $ARGIND }
ENDFILE {
print ""
if (ARGIND < NF) {
ARGV[ARGC] = FILENAME
ARGC++
}
}
$ awk -f tst.awk file
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
que casi no usa memoria pero lee el archivo de entrada una vez por número de campos en una línea, por lo que será mucho más lento que la versión que lee el archivo completo en la memoria. También asume que el número de campos es el mismo en cada línea y usa GNU awk para ENDFILE
y, ARGIND
pero cualquier awk puede hacer lo mismo con pruebas en FNR==1
y END
.