Bash按数字和字长排序按字母顺序排序

时间:2016-04-27 17:11:06

标签: bash sorting numeric

我的数组中有这些字符串:

3 rere 33.33%
2 ena 22.22%
1 something 11.11%
1 som 11.11%
1 ok 11.11%
1 evo 11.11%

预期结果如下:

3 rere 33.33%
2 ena 22.22%
1 something 11.11%
1 evo 11.11%
1 som 11.11%
1 ok 11.11%

它们按编号递减排序。

我想按照中间的单词长度对它们进行排序,但如果单词长度相同,则按字母顺序排序。

这些不是专栏。

我想将它拆分为两个数组,然后对它们进行排序,但是如何将它们连接在一起? 有人有想法吗?

3 个答案:

答案 0 :(得分:3)

您无法按sort的长度排序。我们试试Schwartzian transform

awk '{print length($2), $0}' file | sort -k2,2nr -k1,1nr -k3,3 | cut -d" " -f2-

awk命令需要1 something 11.11%并输出9 1 something 11.11% 然后按数字排序第二个字段,然后按数字顺序排序第一个字段,然后排序第三个字段排序。
然后cut删除第一个字段。

答案 1 :(得分:0)

Perl救援!

perl -l -0777 -aF'\n' -ne '
    print for map join(" ", @$_),
              sort { $b->[0] <=> $a->[0] 
                     || length($a->[1]) <=> length($b->[1])
                     || $a->[1] cmp $b->[1] }
              map [ split ],
              @F;
    ' input-file
  • -n按记录
  • 读取输入记录
  • -0777将整个文件设置为一条记录
  • -l为照片添加换行符
  • -a拆分输入
  • -F'\n'告诉-a拆分换行符
  • 然后每行按split在空格上拆分,按数字(<=>)排序第0列,或按第1列的长度排序,或按字母顺序排序(cmp)第一栏

答案 2 :(得分:0)

这背后的想法与Schwartzian transform中使用的choroba's answer非常相似:我们添加一个排序字段(在本例中是第二列的长度),用它来排序,然后将其删除再次:

while read -r col1 word rest; do
    printf "%d\t%s %s %s\n" "${#word}" "$col1" "$word" "$rest"
done < infile | sort -k 2,2nr -k 1,1nr -k 3,3 | cut -f 2

这导致

3 rere 33.33%
2 ena 22.22%
1 something 11.11%
1 evo 11.11%
1 som 11.11%
1 ok 11.11%

在while循环之后,输出如下所示:

4   3 rere 33.33%
3   2 ena 22.22%
9   1 something 11.11%
3   1 som 11.11%
2   1 ok 11.11%
3   1 evo 11.11%

第二列中有一个新列,其长度为字符串。它的标签分开,以便以后更容易cut

对于sort,我们使用-k参数指定要用于排序的内容(sort并不关心字段是制表符还是空格分隔符号):2,2nr仅使用第二个字段,数字和降序;同样适用于1,1nr,而3,3只是您的标准词汇排序。

输出现在看起来像这样:

4   3 rere 33.33%
3   2 ena 22.22%
9   1 something 11.11%
3   1 evo 11.11%
3   1 som 11.11%
2   1 ok 11.11%

现在我们只需要删除第一列,我们使用cut并利用printf引入的制表符分隔。

Bash while循环非常慢,Perl解决方案可能要快几个数量级。