使用bash水平排序数据

时间:2014-07-31 14:54:20

标签: bash sorting

我在列

中有一个完整的数据文件
sarah mark john
10    20   5
x     y    z 

我想对数据进行排序,以便列保持不变,但第二行的顺序递增,所以它看起来像这样:

john sarah mark
5    10    20 
z    x     y 

我一直在查看sort命令,但只能找到垂直排序,而不是水平排序。我很高兴使用任何工具,任何帮助表示赞赏。 谢谢!

3 个答案:

答案 0 :(得分:7)

让我们创建一个转置文件的功能(使行成为列,列成为行):

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)
              }
        }'
}

这只是将所有数据加载到二维数组a[line,column]中,然后将其打印为a[column,line],以便转置给定的输入。包装器transpose () { }用于将其存储为bash函数。你只需要将它粘贴到你的shell中(如果你想让它成为一个永久函数,可以在~/.bashrc中复制它,只要你打开一个会话就可以使用它。)

然后,通过使用它,我们可以使用sort -n -k2轻松解决问题:根据第2列进行数字排序。然后,转置回来。

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

如果你想要一个漂亮的格式作为最终输出,只需管道到column,如下所示:

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

一步一步:

$ 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
z x y

答案 1 :(得分:1)

来自duplicate question,这会按第一行对列进行排序:

#!/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)

要按第二行排序,请将head -1 $input替换为head -2 $input | tail -1。如果排序应为数字,请放入sort -n -k2而不是sort -k2

答案 2 :(得分:0)

良好的单行完成工作:

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

我在这里找到了它:http://www.unix.com/unix-for-advanced-and-expert-users/36039-horizontal-sorting-lines-file-sed-implementation.html