Using any awk in any shell on every Unix box:
$ cat tst.awk
{
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
vals[rowNr,NR] = $rowNr
}
}
END {
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
for ( colNr=1; colNr<=NR; colNr++ ) {
printf "%s%s", vals[rowNr,colNr], (colNr<NR ? OFS : ORS)
}
}
}
$ awk -f tst.awk file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
You COULD do the above more briefly with:
$ cat tst.awk
{
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
vals[rowNr] = (rowNr in vals ? vals[rowNr] OFS : "") $rowNr
}
}
END {
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
print vals[rowNr]
}
}
$ awk -f tst.awk file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
but note that in that case you're constantly re-assigning new values to the same variable, vals[rowNr]
, which is a relatively slow operation in awk compared to assigning to each new variable once as awk has to determine how much memory will be needed to store the new value, move the old value to that new memory location, append the new value, then free the old location and you end up needing a few large blocks of memory instead of many small ones so it gets harder for awk to find the available memory as the variable size increases. It's also mixing formatting of the output with reading of the input and so the resulting code is more tightly coupled than the first script. It's not terrible for this though and at least the code is concise.