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
Ausgabe
$ 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
Leistung gegen Perl-Lösung von Jonathan in einer 10000-Zeilen-Datei
$ 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 von Ed Morton (@ ghostdog74 kann jederzeit gelöscht werden, wenn Sie dies ablehnen).
Vielleicht hilft diese Version mit einigen expliziteren Variablennamen dabei, einige der folgenden Fragen zu beantworten und allgemein zu klären, was das Skript tut. Es werden auch Tabulatoren als Trennzeichen verwendet, nach denen das OP ursprünglich gefragt hatte, damit leere Felder verarbeitet werden können, und es verschönert zufällig die Ausgabe für diesen speziellen Fall ein wenig.
$ 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
Die oben genannten Lösungen funktionieren in jedem awk (außer natürlich alten, kaputten awk - dort YMMV).
Die oben genannten Lösungen lesen jedoch die gesamte Datei in den Speicher. Wenn die Eingabedateien dafür zu groß sind, können Sie dies tun:
$ 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
Dies verwendet fast keinen Speicher, liest jedoch die Eingabedatei einmal pro Anzahl von Feldern in einer Zeile, sodass sie viel langsamer ist als die Version, die die gesamte Datei in den Speicher liest. Es geht auch davon die Anzahl der Felder in jeder Zeile das gleiche ist und verwendet GNU awk für ENDFILE
und ARGIND
aber jede awk kann auf das gleiche mit Tests durchführen FNR==1
und END
.