对多列进行数字排序

对多列进行数字排序

我正在尝试对有 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 ""}'

那是:

  1. 将每个单元格打印为一行<column-number> <value>
  2. 排序依据价值(注意g(GNU 扩展)而不是nasn不理解+1)并 withLC_ALL=C确保.被识别为十进制基数。
  3. 我们有列号和值。但是为了重建表,我们在这里计算原始数字,每次看到相同的列号时都会递增它
  4. 我们再次调用 sort 来按 raw 排序,然后按 col ( -sfor稳定的也是一个 GNU 扩展)
  5. 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开箱即用地支持这些数字
  • 只考虑.小数基数,无论用户的区域设置如何
  • 具有内置排序和保存表的结构(请注意,GNUawk也可以做到这一点)

这意味着整个输入必须加载到内存中。

<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可以识别所有这些,数字。1231.12-12-12.34sort12e+312+12.30-gsort+1212e+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

相关内容