Using bash to sort data horizontally

I have a file full of data in columns

sarah mark john 10 20 5 xyz 

I want to sort the data so that the columns remain unchanged, but the second row is in ascending order, so it looks like this:

 john sarah mark 5 10 20 zxy 

I looked at the sort command, but was able to find a vertical sort, not a horizontal one. I am glad to use any tool, any help is appreciated. Thanks!

+3
source share
3 answers

Create a function to transpose the file (make rows will become columns and columns will become strings):

 transpose () { awk '{for (i=1; i<=NF; i++) a[i,NR]=$i; max=(max<NF?NF:max)} END {for (i=1; i<=max; i++) {for (j=1; j<=NR; j++) printf "%s%s", a[i,j], (j<NR?OFS:ORS) } }' } 

This simply loads all the data into a two-dimensional array a[line,column] , and then prints it as a[column,line] , so that it wraps the given input. The transpose () { } wrapper is used to store it as a bash function. You just need to copy it to the shell (or to ~/.bashrc if you want it to be a constant function available anytime you open a session).

Then, using this, we can easily solve the problem using sort -n -k2 : sort numerically based on column 2. Then rearrange.

 $ cat a | transpose | sort -n -k2 | transpose john sarah mark 5 10 20 zxy 

If you want to have a good format as the final output, just connect to column as follows:

 $ cat a | transpose | sort -n -k2 | transpose | column -t john sarah mark 5 10 20 zxy 

Step by step:

 $ cat a | transpose sarah 10 x mark 20 y john 5 z $ cat a | transpose | sort -n -k2 john 5 z sarah 10 x mark 20 y $ cat a | transpose | sort -n -k2 | transpose john sarah mark 5 10 20 zxy 
+7
source

Based on a repeating question , this sorts the columns by the first row:

 #!/bin/bash input="$1" order=$((for i in $(head -1 $input); do echo $i; done) | nl | sort -k2 | cut -f1) grep ^ $input | (while read line do read -a columns <<< "${line%"${line##*[![:space:]]}"}" orderedline=() for i in ${order[@]} do orderedline+=("${columns[$i - 1]}") done line=$(printf "\t%s" "${orderedline[@]}") echo ${line:1} done) 

To sort by the second line, replace head -1 $input with head -2 $input | tail -1 head -2 $input | tail -1 . If sorting should be numeric, enter sort -n -k2 instead of sort -k2 .

+1
source

A good one-line line does its job:

perl -ane '$,=" "; print sort @F; print "\n";' file

I found it here: http://www.unix.com/unix-for-advanced-and-expert-users/36039-horizontal-sorting-lines-file-sed-implementation.html

0
source

Source: https://habr.com/ru/post/1205277/


All Articles