按“行内容”频率对文件进行排序 - 打印重复项

按“行内容”频率对文件进行排序 - 打印重复项

假设有一个文件 -

a
b
b
b
b
c
c
d
d
d

我希望根据频率对输出进行排序(我希望重复的行也被打印出来) -

b
b
b
b
d
d
d
c
c
a

答案1

使用 GNU Awk:

gawk '
   { arr[$0]++ }
   END {
        PROCINFO["sorted_in"] = "@val_num_desc"
        for (ln in arr) for (i = 1; i <= arr[ln]; i++) print ln
       }
   '

诀窍是使用数组和@val_num_desc。每遇到一行都会变成一个索引,每次出现该行时,相关值都会增加。最后,我们按特定顺序扫描整个数组:

"@val_num_desc"
[…] 元素值被视为数字,按从高到低的顺序排列。

来源

因此,外部(第一个)for负责按所需顺序检索行及其频率;内部(第二个)for只是按正确的次数打印当前选定的行。

笔记:

  • 每个字符都很重要。一行和带有额外尾随空格的同一行是不同的。

答案2

下面的操作将实现您想要的效果...不过还有许多其他方法可以实现这一点...例如gawk,按照卡米尔 (Kamil) 的回答。

  • 第一个sort将按行数据排序
  • uniq -c将计算匹配出现的次数(它们必须是邻居)
  • sort -nr将按出现次数反向排序
  • 循环while遍历每一行
    • read n l将计数输入到n,并将行数据输入到l
  • 循环for将迭代n次数
  • echo "${l}"输出线数据
(
    sort \
        | uniq -c \
        | sort -nr \
        | while read n l; do \
            for i in $(seq ${n}); do \
                echo "${l}"; \
            done; \
        done
) <<"EOF"
a
b
b
b
b
c
c
d
d
d
EOF

相关内容