Як я можу підрахувати кількість різних символів у файлі?


19

Мені потрібна програма, яка виводить кількість різних символів у файлі. Приклад:

> stats testfile
' ': 207
'e': 186
'n': 102

Існує якийсь інструмент, що це робить?

Відповіді:


21

Слід працювати:

$ sed 's/\(.\)/\1\n/g' text.txt | sort | uniq -c

Спочатку ми вставляємо новий рядок після кожного символу, ставлячи кожного символу у свій рядок. Потім ми їх сортуємо. Потім ми використовуємо команду uniq для видалення дублікатів, префіксуючи кожен рядок числом зустрічань цього символу.

Щоб сортувати список за частотою, вставте все це sort -nr.


4
На sed для Mac OS X цеsed 's/\(.\)/\1\'$'\n/g' text.txt
mb21

Дуже приємно, але, на жаль, він не працює правильно, якщо текст містить символи Unicode (utf8). Можливо, є спосіб зробити sedце, але рішення Python Якова Влійма спрацювало для мене добре.
bitinerant

14

Рішення Стівена - це гарне, просте. Це не настільки ефективно для дуже великих файлів (файлів, які не зручно розміщуються приблизно в половині оперативної пам'яті) через крок сортування. Ось awk версія. Це також трохи складніше , тому що він намагається зробити правильну річ для кількох спеціальних символів (символ нового рядка, ', \, :).

awk '
  {for (i=1; i<=length; i++) ++c[substr($0,i,1)]; ++c[RS]}
  function chr (x) {return x=="\n" ? "\\n" : x==":" ? "\\072" :
                           x=="\\" || x=="'\''" ? "\\" x : x}
  END {for (x in c) printf "'\''%s'\'': %d\n", chr(x), c[x]}
' | sort -t : -k 2 -r | sed 's/\\072/:/'

Ось рішення Perl за тим же принципом. Перевага Perl полягає в тому, що він може сортувати внутрішньо. Також це правильно не буде рахувати додатковий новий рядок, якщо файл не закінчується символом нової лінії.

perl -ne '
  ++$c{$_} foreach split //;
  END { printf "'\''%s'\'': %d\n", /[\\'\'']/ ? "\\$_" : /./ ? $_ : "\\n", $c{$_}
        foreach (sort {$c{$b} <=> $c{$a}} keys %c) }'

1
+1 за те, що не робили цього жахливого
вигляду

1

Повільна, але відносно зручна для пам'яті версія, що використовує рубін. Близько десятка МБ оперативної пам’яті незалежно від розміру вводу.

# count.rb
ARGF.
  each_char.
  each_with_object({}) {|e,a| a[e] ||= 0; a[e] += 1}.
  each {|i| puts i.join("\t")}

ruby count.rb < input.txt
t       20721
d       20628
S       20844
k       20930
h       20783
... etc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.