我正在尝试对有 600 列的文件进行排序。我希望它给我顶部所有最高的数字(每个字段的降序)我只是对以空格分隔的文件进行切片,看看它是否工作正常。我尝试了这些命令,但似乎我做错了什么
$ cat test.txt
+0.07273 +0.67860
-6.99580 -0.44278
-7.21295 +0.19793
$ sort -nr test.txt # (just sorted column one)
-7.21295 +0.19793
-6.99580 -0.44278
+0.07273 +0.67860
$ sort -k1,1nr -k2,2nr test.txt # (just sorted column one)
+0.0727 +0.67860
-6.99580 -0.44278
-7.21295 +0.19793
我如何按降序对整个列进行排序。很难使用 k 600 次
答案1
你可以这样做:
<test.txt awk '{for (c = 1; c<=NF; c++) print c, $c}' |
LC_ALL=C sort -k2,2rg |
awk '{print $1, r[$1]++, $2}' |
sort -sk2,2n -k1,1n | awk '
{printf "%s", ($2 == prev ? (NR == 1 ? "" : " ") : "\n") $3; prev = $2}
END {print ""}'
那是:
- 将每个单元格打印为一行
<column-number> <value>
。 - 排序依据价值(注意
g
(GNU 扩展)而不是n
asn
不理解+
1)并 withLC_ALL=C
确保.
被识别为十进制基数。 - 我们有列号和值。但是为了重建表,我们在这里计算原始数字,每次看到相同的列号时都会递增它
- 我们再次调用 sort 来按 raw 排序,然后按 col (
-s
for稳定的也是一个 GNU 扩展) - 并
awk
处理这些内容以再次按列打印。
就在最后一步之前,根据您的输入,给出:
1 0 +0.07273
2 0 +0.67860
1 1 -6.99580
2 1 +0.19793
1 2 -7.21295
2 2 -0.44278
这awk
变成:
+0.07273 +0.67860
-6.99580 +0.19793
-7.21295 -0.44278
每列按数字从最大到最小排序。
现在,您可能会发现使用perl
哪个更容易:
+1.123
开箱即用地支持这些数字- 只考虑
.
小数基数,无论用户的区域设置如何 - 具有内置排序和保存表的结构(请注意,GNU
awk
也可以做到这一点)
这意味着整个输入必须加载到内存中。
<test.txt perl -lane '
my $n; push @{$c[$n++]}, $_ for @F;
END {
@{$_} = sort {$b <=> $a} @{$_} for @c; # sort the columns in
# reverse-numerical order
for ($r = 0; $r < $.; $r++) {
print join " ", map {$c[$_]->[$r]} (0..$#c)
}
}'
1 对于,仅识别格式为、或 的数字-n
(带有可选的前导空格)。要获取键的值,请从字符串开头获取与该模式匹配的部分,在 的情况下,即。在 的情况下,它是空字符串,因此。通过,GNU可以识别所有这些,数字。123
1.12
-12
-12.34
sort
12e+3
12
+12.3
0
-g
sort
+12
12e+3
$ printf '%s\n' 1 2 10 2e3 +2 +10 inf +1 | sort -n
+1
+10
+2
inf
1
2
2e3
10
$ printf '%s\n' 1 2 10 2e3 +2 +10 inf +1 | sort -g
1
+1
2
+2
10
+10
2e3
inf