------------------------------------------------------------------------ Convert a column to a matrix ------------------------------------------------------------------------ Say you have a column of data, length n, and you wish to write it as a matrix with dimensions (nr,nc) where nr is the number of rows and nc is the number of columns. For the purpose of this exercise we will generate the requisite column in one of several ways: $ echo {01..12} | xargs -n 1 | tee infile 01 02 03 04 05 06 07 08 09 10 11 12 $ paste -d "\n" <(seq 12) | tee infile #generates a similar file $ seq 12 | paste -d "\n" - | tee infile #ditto $ seq 12 | xargs -n 1 | tee infile #ditto Say you want to convert "infile" to (3,4) matrix. This is easily done: $ cat infile | xargs -n 3 01 02 03 04 05 06 07 08 09 10 11 12 But say, you wanted the transpose. I thought it was not possible to do with standard Unix tools. So I wrote a program which can do this. However, recently, I discovered a pure Unix tool approach and this is described in "pr" (see Tools webpage). In any case, here is the program. $ col2mat -n 3 infile 01 04 07 10 02 05 08 11 03 06 09 12 The program can also use other delimiters: $ col2mat -n 3 -d "," infile 01,04,07,10 02,05,08,11 03,06,09,12 ------------------------------------------------------------------------ $ cat col2mat ------------------------------------------------------------------------ #!/bin/bash # # col2mat -n nrow [-d delim] infile # # print matrix (nrow, ncol) of infile which has N rows (N=nrow*ncol) # delim is single-char delimator such as , : ";" "\t" # # example # $ seq 9 # # $ col2mat -n 3 <(seq 9) # 1 4 7 # 2 5 8 # 3 6 9 # $ col2mat -n 3 -d : <(seq 9) # limitations: number of rows < 100 if [ $# -lt 3 ] || [ $# -eq 4 ]; then printf "incorrect number of arguments %d\n" $#; exit -1 fi if [ $# -eq 3 ]; then if [ $1 != "-n" ]; then printf "%s: incorrect option\n" $1; exit -1 fi nrow=$2; fs=" "; shift 2 else if [ $1 != "-n" ] || [ $3 != "-d" ]; then printf "%s %s: incorrection option(s)\n" $1, $3; exit -1 fi nrow=$2; fs=$4; shift 4 fi if [ $nrow -ge 100 ]; then printf "requesting %d rows which exceed limit\n" $nrow exit -1 fi awk -v nr=$nrow '{ i=int((NR-1)/nr+1) ind=sprintf("%02d",i) print $0 > "T_" ind ".tmp"}' $1 paste -d "$fs" T_[0-9][1-9].tmp rm T_[0-9][1-9].tmp #clean up