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
вихід
$ 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
Продуктивність проти рішення Perl Джонатана у файлі 10000 рядків
$ 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 by Ed Morton (@ ghostdog74 сміливо видаляйте, якщо ви не схвалюєте).
Можливо, ця версія з деякими більш чіткими назвами змінних допоможе відповісти на деякі питання нижче та загалом уточнити, що робить сценарій. Він також використовує вкладки як сепаратор, про який спочатку запитував ОП, щоб він обробляв порожні поля, і він збіг обробляти вихідний результат для цього конкретного випадку.
$ 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
Вищезазначені рішення працюватимуть у будь-який awk (крім старого, зламаного awk звичайно - там YMMV).
Вищезазначені рішення дійсно читають весь файл у пам'яті - якщо вхідні файли занадто великі для цього, ви можете зробити це:
$ 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
який майже не використовує пам'ять, але читає вхідний файл один раз на кількість полів у рядку, тому він буде набагато повільніше, ніж версія, яка читає весь файл у пам'ять. Він також припускає , що кількість полів однаково на кожному рядку , і він використовує GNU AWK для ENDFILE
і ARGIND
але будь-який AWK може зробити те ж саме з тестами на FNR==1
і END
.