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
production
$ 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
Performance par rapport à la solution Perl de Jonathan sur un fichier de 10000 lignes
$ 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
EDIT par Ed Morton (@ ghostdog74 n'hésitez pas à supprimer si vous désapprouvez).
Peut-être que cette version avec des noms de variables plus explicites aidera à répondre à certaines des questions ci-dessous et à clarifier généralement ce que fait le script. Il utilise également des tabulations comme séparateur que l'OP avait initialement demandé afin de gérer les champs vides et cela par coïncidence embellit un peu la sortie pour ce cas particulier.
$ 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
Les solutions ci-dessus fonctionneront dans n'importe quel awk (sauf l'ancien awk cassé bien sûr - il y a YMMV).
Les solutions ci-dessus lisent cependant le fichier entier en mémoire - si les fichiers d'entrée sont trop volumineux pour cela, vous pouvez le faire:
$ 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
qui n'utilise presque pas de mémoire mais lit le fichier d'entrée une fois par nombre de champs sur une ligne, il sera donc beaucoup plus lent que la version qui lit le fichier entier en mémoire. Il suppose également que le nombre de champs est le même sur chaque ligne et utilise GNU awk pour ENDFILE
et ARGIND
mais tout awk peut faire la même chose avec des tests sur FNR==1
et END
.