transpose—Perform a Matrix Transposition

Contributed by Geoff Clare

transpose performs a matrix transposition on its input. I wrote this when I saw a script to do this job posted to the Net and thought it was horribly inefficient. I posted mine as an alternative with timing comparisons. If I remember rightly, the original one stored all the elements individually and used a nested loop with a printf for each element. It was immediately obvious to me that it would be much faster to construct the rows of the transposed matrix “on the fly.”

My script uses ${1+"$@"} to supply file names on the awk command line so that if no files are specified awk will read its standard input. This is much better than plain $* which can’t handle filenames containing whitexspace.

#! /bin/sh
# Transpose a matrix: assumes all lines have same number
# of fields

exec awk '
NR == 1 {
	n = NF
	for (i = 1; i <= NF; i++)
		row[i] = $i
	if (NF > n)
		n = NF
	for (i = 1; i <= NF; i++)
		row[i] = row[i] " " $i
	for (i = 1; i <= n; i++)
		print row[i]
}' ${1+"$@"}

Here’s a test file:

1 2 3 4
5 6 7 8
9 10 11 12

Now we run transpose on the file.

$ transpose test
1 5 9
2 6 10
3 7 11
4 8 12

Program Notes for transpose

This is a very simple but interesting script. It creates an array named row and appends each field into an element of the array. The END procedure outputs the array.

Get sed & awk, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience live online training, plus books, videos, and digital content from nearly 200 publishers.