Làm cách nào để đếm số lượng ký tự khác nhau trong một tệp?


19

Tôi sẽ cần một chương trình, xuất ra số lượng các ký tự khác nhau trong một tệp. Thí dụ:

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

Tồn tại bất kỳ công cụ, mà làm điều này?

Câu trả lời:


21

Sau đây nên làm việc:

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

Đầu tiên, chúng tôi chèn một dòng mới sau mỗi ký tự, đặt mỗi ký tự trên dòng riêng. Sau đó, chúng tôi sắp xếp nó. Sau đó, chúng tôi sử dụng lệnh uniq để loại bỏ các bản sao, tiền tố mỗi dòng với số lần xuất hiện của ký tự đó.

Để sắp xếp danh sách theo tần suất, hãy đưa tất cả vào sort -nr.


4
Trên sed cho Mac OS X, nósed 's/\(.\)/\1\'$'\n/g' text.txt
mb21

Rất đẹp, nhưng thật không may, nó không hoạt động chính xác nếu văn bản chứa các ký tự Unicode (utf8). Có thể có một cách để thực hiện sedđiều này, nhưng giải pháp Python của Jacob Vlijm hoạt động tốt với tôi.
bitinerant

14

Giải pháp của Steven là một giải pháp tốt, đơn giản. Nó không hiệu quả đối với các tệp rất lớn (các tệp không vừa vặn trong khoảng một nửa RAM của bạn) do bước sắp xếp. Đây là một phiên bản awk. Nó cũng là một chút phức tạp hơn vì nó cố gắng làm điều đúng cho một vài ký tự đặc biệt (dòng mới, ', \, :).

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/:/'

Đây là một giải pháp Perl trên cùng một nguyên tắc. Perl có lợi thế là có thể sắp xếp nội bộ. Ngoài ra, điều này sẽ không chính xác không tính thêm một dòng mới nếu tệp không kết thúc bằng một ký tự dòng mới.

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

1
+1 vì đã không làm điều đó kinh khủng
Sparr

1

Một phiên bản chậm nhưng tương đối thân thiện với bộ nhớ, sử dụng ruby. Khoảng một chục MB RAM, bất kể kích thước đầu vào.

# 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.