Как я могу группировать числа в файле

У меня есть файл с числами в формате float.
Я могу просмотреть их через sort -rn numbers.txt | less sort -rn numbers.txt | less
Я хотел бы хотя бы «сгруппировать» их. Т.е. легко увидеть, сколько в одном диапазоне.
Чтобы привести пример файла:

 30.9695041179657 30.8851490020752 30.2127060890198 29.1361880302429 26.4587681293488 25.8535399436951 25.7361891269684 25.7305450439453 25.1068568229675 24.7598769664764 24.3106801509857 24.0782940387726 

Меня не волнует точность. Поэтому я хотел бы знать, сколько 25 в файле, например, в этом случае 4 и 30 и т. Д. Для всех номеров в файле.
Таким образом, для этого примера вывод выглядит следующим образом: 3 для 30, 1 для 29, 1 для 26, 4 для 25, 3 для 24.
Есть простой способ сделать это?

  • `pwd`, но опустить первые n каталогов
  • Переименовать все пробелы в именах файлов изображений внутри html php-файлов
  • Как вставить содержимое файла в другой файл перед шаблоном (маркером)?
  • Очень простой вопрос H / W с использованием трубы и grep
  • BSD sed: заменить только N-е вхождение шаблона
  • Преобразование простых данных в json-файл
  • В POSIX sed период (точка) соответствует новой строке в многострочном пространстве шаблонов?
  • Зацикливание файлов с пробелами в именах?
  • 9 Solutions collect form web for “Как я могу группировать числа в файле”

    Как насчет

     cut -d. -f1 numbers.txt | sort | uniq -c 

    Используя данные примера,

     $ cut -d. -f1 numbers.txt | sort | uniq -c 3 24 4 25 1 26 1 29 3 30 

    С awk ( mawk ):

     $ awk -F . '{COUNTS[$1]++} END{for(ct in COUNTS) {printf("%d %d time(s)\n", ct, COUNTS[ct])}}' test.txt 30 3 time(s) 24 3 time(s) 25 4 time(s) 26 1 time(s) 29 1 time(s) 

    Параметр -F устанавливает разделитель полей ( FS ) в . , кроме этого мы проходим через все строки с помощью {COUNTS[$1]++} , используя $1 как часть перед разделителем ( . ) и сохраняем запись о том, сколько раз мы сталкиваемся с ними в массиве с именем COUNTS .

    В конце ( END {} ) мы сбрасываем то, что мы нашли. Как вы видите, большая часть – это выход.

    Немного читаем в файле:

     {COUNTS[$1]++} END { for(ct in COUNTS) { printf("%d %d time(s)\n", ct, COUNTS[ct]) } } 

    Вы можете использовать awk :

     awk '{a[int($1)]++}END{for (i in a) {print a[i], i}}' inputfile 

    Если вы хотите, чтобы результат сортировался, проведите вывод для sort :

     awk '{a[int($1)]++}END{for (i in a) {print a[i], i}}' inputfile | sort -k2 

    Для ввода вашего образца это приведет к:

     3 24 4 25 1 26 1 29 3 30 

    В perl :

     perl -lan -F'\.' -e '$count{$F[0]}++; END{ print "$_ --> $count{$_}" for sort {$a <=> $b} keys %count }' your_file 

    редактировать

    Вероятно, более эффективно:

     perl -ne ' $count{int()}++; END{ print "$_ --> $count{$_}" for sort {$a <=> $b} keys %count }' your_file 
     cut -b-2 numbers.txt | sort -n | uniq -c | sort -nr 

    cut -b-2 выбирает два первых символа, sort -nr сначала сортирует результаты по самой высокой частоте

    Результат:

      4 25 3 30 3 24 1 29 1 26 

    Или как питон oneliner, просто для этого:

     python -c 'l = [x[:2] for x in open("numbers.txt").readlines()];print(list(reversed(sorted([(l.count(x),x) for x in set(l)]))))' 

    Результат:

     [(4, '25'), (3, '30'), (3, '24'), (1, '29'), (1, '26')] 

    Кажется, что ваш файл отсортирован, поэтому вы можете сделать так:

     $ uniq -c <(perl -pe 's/\.\d*//' file) 3 30 1 29 1 26 4 25 3 24 

    Если он не был отсортирован:

     $ uniq -c <(perl -pe 's/\.\d*//' file | sort -rn) 3 30 1 29 1 26 4 25 3 24 

    Подход GNU coreutils + grep:

     $ grep -oP '^\d+' file | sort | uniq -c 3 24 4 25 1 26 1 29 3 30 

    Флаг -o сообщает grep печатать только соответствующую часть строки, а -P активирует регулярные выражения Perl Compatible Regular, которые позволяют нам использовать \d для чисел. Таким образом, grep будет печатать самый длинный отрезок цифр, найденный в начале строки (т. Е. Все до первой не-цифры,.), А затем sort сортировку вывода, а uniq -c подсчитывает количество вхождений каждой строки на входе.

    Другой подход Perl:

     $ perl -lne '/^\d+/ && $k{$&}++; END{print "$k{$_} : $_" for sort keys %k}' file 3 : 24 4 : 25 1 : 26 1 : 29 3 : 30 

    $& – строка, совпадающая в предыдущей операции совпадения, поэтому мы сохраняем ее в хеш ( %k ) и увеличиваем ее значение на единицу. Блок END будет печатать каждый найденный номер ( $_ ) и значение, которое он имеет в хэше ( $k{$_} ), количество раз, когда оно было найдено.

    И подход bash (> = версия 4) ассоциативных массивов:

     $ while IFS='\.' read -rab; do (( ll[$a]++ )); done < file; for i in ${!ll[@]} ; do echo ${ll[$i]} : $i; done 3 : 24 4 : 25 1 : 26 1 : 29 3 : 30 

    IFS установлен . означает, что входные строки разделены на записи . так что $a будет первым числом до . , Мы перебираем через них и используем их как ключи к ассоциативному массиву, значение которого увеличивается каждый раз, когда число найдено. Затем, как только массив будет заполнен, мы перебираем список ключей ( ${!ll[@]} ) и печатаем каждую клавишу и ее значение (количество раз, когда оно было замечено).

    Использование datamash bin GNU datamash :

     datamash -s bin:1 1 < num | datamash -s -g 1 count 1 

    Вывод:

     24 3 25 4 26 1 29 1 30 3 

    С мельником :

     $> mlr --from data.txt --ocsv put '$1=int(ceil($1))' then count-distinct -f 1 1,count 31,3 30,1 27,1 26,4 25,3 
    Linux и Unix - лучшая ОС в мире.