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
keluaran
$ 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
Kinerja terhadap solusi Perl oleh Jonathan pada file 10.000 baris
$ 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 oleh Ed Morton (@ ghostdog74 jangan ragu untuk menghapusnya jika Anda tidak setuju).
Mungkin versi ini dengan beberapa nama variabel yang lebih eksplisit akan membantu menjawab beberapa pertanyaan di bawah ini dan secara umum menjelaskan apa yang dilakukan skrip. Ini juga menggunakan tab sebagai pemisah yang awalnya diminta OP sehingga akan menangani bidang kosong dan secara kebetulan meningkatkan sedikit keluaran untuk kasus khusus ini.
$ 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
Solusi di atas akan bekerja di sembarang awk (kecuali awk lama, rusak tentu saja - ada YMMV).
Solusi di atas memang membaca seluruh file ke dalam memori - jika file input terlalu besar untuk itu maka Anda dapat melakukan ini:
$ 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
yang menggunakan hampir tidak ada memori tetapi membaca file input sekali per jumlah kolom dalam satu baris sehingga akan jauh lebih lambat daripada versi yang membaca seluruh file ke dalam memori. Ini juga mengasumsikan jumlah bidang sama pada setiap baris dan menggunakan GNU awk for ENDFILE
dan ARGIND
tetapi awk apa pun dapat melakukan hal yang sama dengan pengujian pada FNR==1
dan END
.