Diagonal Output of a file
awk solution, not as elegant as @don_chrissti solution, but works where not a square.
awk -F, '{a=a$++n" "}END{print a}' file
Python and numpy
The input data that we're looking at can be treated as a matrix or 2-dimensional array. Now, if we approach the problem from this point of view, there's several computational tools that can be used for manipulating matrices. In particular, Python's numpy
module allows that. Thus, we could use two things - the loadtxt()
function and diagonal()
to extract the desired data:
$ python -c 'import sys,numpy;a=numpy.loadtxt(sys.argv[1],dtype=int,delimiter=",");print( a.diagonal() )' input.txt
[1 7 3 9 5]
Now, this is the big chunk of the job done. To make the output pretty, we just need to convert the obtained data to strings, and create a space-separated string out of individual ones. Like so:
$ python -c 'import sys,numpy;a=numpy.loadtxt(sys.argv[1],delimiter=",");print(" ".join( [ str(int(i)) for i in a.diagonal() ]))' input.txt
1 7 3 9 5
Of course, all this doesn't have to be done as one-liner. For the sake of readability we can make a small script, which will also allow us to process all filenames given as arguments on command-line:
#!/usr/bin/env python
import sys
import numpy as np
for filename in sys.argv[1:]:
data=np.loadtxt(filename,delimiter=",")
diag = data.diagonal()
result_string = " ".join( [ str(int(i)) for i in diag ] )
print(result_string)
POSIX shell:
n=0 while IFS=',' && read x ; do set -- $x ; shift $n ; echo "$1" ; n=$((n+1)) done < inputfile
bash
can be more concise:n=0; while IFS=',' read -a x ; do echo "${x[((n++))]}" ; done < inputfile
Note that it's easy to get diagonals for all four rotations of the data by filtering to tac
and rev
, (or tac
alone -- if the data is a square .csv array). POSIX shell examples, but first make some new asymmetric input values:
seq 25 | paste -d, - - - - - | tee asym_input
Output:
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
16,17,18,19,20
21,22,23,24,25
A
\
left to right diagonal, (the OP question, with different input):n=0 while IFS=',' && read x ; do set -- $x ; shift $n ; echo "$1" ; n=$((n+1)) done < asym_input
Output:
1 7 13 19 25
A
/
left to right diagonal:n=0 tac asym_input | while IFS=',' && read x ; do set -- $x ; shift $n ; echo "$1" ; n=$((n+1)) done
Output:
21 17 13 9 5
A
/
right to left diagonal:n=0 rev asym_input | while IFS=',' && read x ; do set -- $x ; shift $n ; echo "$1" ; n=$((n+1)) done | rev
Output:
5 9 13 17 21
A
\
right to left diagonal:n=0 tac asym_input | rev | while IFS=',' && read x ; do set -- $x ; shift $n ; echo "$1" ; n=$((n+1)) done | rev
Output:
25 19 13 7 1