Сортировка файлов по частоте "содержание строки" - печать дубликатов

Представь, что есть файл -

a
b
b
b
b
c
c
d
d
d

Я хочу, чтобы выходные данные были отсортированы по частоте (я хочу, чтобы дублированные строки также печатались), а также -

b
b
b
b
d
d
d
c
c
a

2 ответа

Решение

С 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 просто печатать выбранную строку нужное количество раз.

Замечания:

  • Каждый персонаж имеет значение. Строка и та же строка с дополнительным пробелом различаются.

Следующее сделает то, что вам нужно... хотя есть много других способов добиться этого... например, с gawkсогласно ответу Камиля.

  • Первый 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
Другие вопросы по тегам