我有一个充满数据列的文件
sarah mark john
10 20 5
x y z
我想对数据进行排序,使列保持不变,但第二行按递增顺序排列,所以它看起来像这样:
john sarah mark
5 10 20
z x y
我一直在看排序命令,但只能找到垂直排序,而不是水平排序。我很乐意使用任何工具,任何帮助都很感激。谢谢你!
让我们创建一个函数来转换文件(使行变为列,列变为行):
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
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
z x y
来自一个重复的问题,这将按第一行对列进行排序:
#!/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
。
好的一行代码可以完成工作:
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