我在列
中有一个完整的数据文件sarah mark john
10 20 5
x y z
我想对数据进行排序,以便列保持不变,但第二行的顺序递增,所以它看起来像这样:
john sarah mark
5 10 20
z x y
我一直在查看sort命令,但只能找到垂直排序,而不是水平排序。我很高兴使用任何工具,任何帮助表示赞赏。 谢谢!
答案 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