2010-11-13 32 views
6

Tôi đã có một tệp văn bản được tạo bằng phần mềm OCR - có kích thước khoảng một megabyte. Một số ký tự không phổ biến xuất hiện trên tất cả tài liệu và hầu hết trong số đó là lỗi OCR.Cách thu thập số liệu thống kê sử dụng ký tự trong tệp văn bản bằng các lệnh Unix?

Tôi muốn tìm tất cả các ký tự được sử dụng trong tài liệu để dễ dàng phát hiện lỗi (như lệnh UNIQ nhưng đối với ký tự, không phải cho các dòng).

Tôi đang sử dụng Ubuntu. Lệnh Unix nào tôi nên sử dụng để hiển thị tất cả các ký tự được sử dụng trong tệp văn bản?

Trả lời

8

này nên làm những gì bạn đang tìm kiếm:

cat inputfile | sed 's/\(.\)/\1\n/g' | sort | uniq -c 

Những tiền đề là các sed đặt mỗi nhân vật trong các tập tin vào một dòng của chính nó, thì sort | uniq -c chuỗi thông thường dải ra tất cả nhưng một trong số mỗi ký tự duy nhất xảy ra và cung cấp số lần mỗi lần xảy ra.

Ngoài ra, bạn có thể thêm | sort -n vào cuối toàn bộ chuỗi để sắp xếp đầu ra theo số lần mỗi ký tự xảy ra. Ví dụ:

$ echo hello | sed 's/\(.\)/\1\n/g' | sort | uniq -c | sort -n 
    1 
    1 e 
    1 h 
    1 o 
    2 l 
+0

Đến đây để đăng chính xác này. Nhưng than ôi tôi quá chậm. Nhưng đây là một gợi ý hữu ích. Cuối cùng, nếu bạn muốn tất cả trên một dòng, bạn có thể thêm "| perl -pe 'chomp'" – OmnipotentEntity

+0

Cảm ơn rất nhiều. Đó là chính xác những gì tôi đang tìm kiếm. Sạch sẽ và đơn giản – Hali

0

Khi sử dụng lệnh * nix, câu trả lời ở trên là tốt nhưng không nhận được thống kê sử dụng.

Tuy nhiên, nếu bạn thực sự muốn thống kê (như sử dụng hiếm nhất, trung bình, được sử dụng nhiều nhất, v.v.) trên tệp, Python này nên thực hiện.

def get_char_counts(fname): 
    f = open(fname) 
    usage = {} 
    for c in f.read(): 
     if c not in usage: 
      usage.update({c:1}) 
     else: 
      usage[c] += 1 
    return usage 
+0

Nhưng cũng có số liệu thống kê trong các câu trả lời ở trên. Cám ơn bạn vì đã trả lời câu hỏi của mình. – Hali

+0

@Hali - Không thấy chỉnh sửa ở trên (Và câu trả lời cũng cần một đoạn của Python;) – new123456

1

này sẽ làm điều đó:

#!/usr/bin/perl -n 
# 
# charcounts - show how many times each code point is used 
# Tom Christiansen <[email protected]> 

use open ":utf8"; 

++$seen{ ord() } for split //; 

END { 
    for my $cp (sort {$seen{$b} <=> $seen{$a}} keys %seen) { 
     printf "%04X %d\n", $cp, $seen{$cp}; 
    } 
} 

Run trên chính nó, chương trình sản xuất:

$ charcounts /tmp/charcounts | head 
0020 46 
0065 20 
0073 18 
006E 15 
000A 14 
006F 12 
0072 11 
0074 10 
0063 9 
0070 9 

Nếu bạn muốn các ký tự chữ và/hoặc tên của nhân vật cũng vậy, thật dễ dàng để thêm vào.

Nếu bạn muốn điều gì đó tinh vi hơn, chương trình này tính toán các ký tự theo thuộc tính Unicode. Nó có thể là đủ cho mục đích của bạn, và nếu không, bạn sẽ có thể thích ứng với nó.

#!/usr/bin/perl 
# 
# unicats - show character distribution by Unicode character property 
# Tom Christiansen <[email protected]> 

use strict; 
use warnings qw<FATAL all>; 

use open ":utf8"; 

my %cats; 

our %Prop_Table; 
build_prop_table(); 

if (@ARGV == 0 && -t STDIN) { 
    warn <<"END_WARNING"; 
$0: reading UTF-8 character data directly from your tty 
\tSo please type stuff... 
\t and then hit your tty's EOF sequence when done. 
END_WARNING 

} 

while (<>) { 
    for (split(//)) { 

     $cats{Total}++; 

     if (/\p{ASCII}/) { $cats{ASCII}++ } 
     else    { $cats{Unicode}++ } 

     my $gcat = get_general_category($_); 
     $cats{$gcat}++; 

     my $subcat = get_general_subcategory($_); 
     $cats{$subcat}++; 

    } 
} 

my $width = length $cats{Total}; 

my $mask = "%*d %s\n"; 

for my $cat(qw< Total ASCII Unicode >) { 
    printf $mask, $width => $cats{$cat} || 0, $cat; 
} 
print "\n"; 

my @catnames = qw[ 
    L Lu Ll Lt Lm Lo 
    N Nd Nl No 
    S Sm Sc Sk So 
    P Pc Pd Ps Pe Pi Pf Po 
    M Mn Mc Me 
    Z Zs Zl Zp 
    C Cc Cf Cs Co Cn 
]; 

#for my $cat (sort keys %cats) { 
for my $cat (@catnames) { 
    next if length($cat) > 2; 
    next unless $cats{$cat}; 

    my $prop = length($cat) == 1 
       ? (" " . q<\p> . $cat   ) 
       : (  q<\p> . "{$cat}" . "\t") 
      ; 

    my $desc = sprintf("%-6s %s", $prop, $Prop_Table{$cat}); 

    printf $mask, $width => $cats{$cat}, $desc; 
} 

exit; 

sub get_general_category { 
    my $_ = shift(); 
    return "L" if /\pL/; 
    return "S" if /\pS/; 
    return "P" if /\pP/; 
    return "N" if /\pN/; 
    return "C" if /\pC/; 
    return "M" if /\pM/; 
    return "Z" if /\pZ/; 

    die "not reached one: $_"; 
} 

sub get_general_subcategory { 
    my $_ = shift(); 

    return "Lu" if /\p{Lu}/; 
    return "Ll" if /\p{Ll}/; 
    return "Lt" if /\p{Lt}/; 
    return "Lm" if /\p{Lm}/; 
    return "Lo" if /\p{Lo}/; 

    return "Mn" if /\p{Mn}/; 
    return "Mc" if /\p{Mc}/; 
    return "Me" if /\p{Me}/; 

    return "Nd" if /\p{Nd}/; 
    return "Nl" if /\p{Nl}/; 
    return "No" if /\p{No}/; 

    return "Pc" if /\p{Pc}/; 
    return "Pd" if /\p{Pd}/; 
    return "Ps" if /\p{Ps}/; 
    return "Pe" if /\p{Pe}/; 
    return "Pi" if /\p{Pi}/; 
    return "Pf" if /\p{Pf}/; 
    return "Po" if /\p{Po}/; 

    return "Sm" if /\p{Sm}/; 
    return "Sc" if /\p{Sc}/; 
    return "Sk" if /\p{Sk}/; 
    return "So" if /\p{So}/; 

    return "Zs" if /\p{Zs}/; 
    return "Zl" if /\p{Zl}/; 
    return "Zp" if /\p{Zp}/; 

    return "Cc" if /\p{Cc}/; 
    return "Cf" if /\p{Cf}/; 
    return "Cs" if /\p{Cs}/; 
    return "Co" if /\p{Co}/; 
    return "Cn" if /\p{Cn}/; 

    die "not reached two: <$_> " . sprintf("U+%vX", $_); 

} 

sub build_prop_table { 

    for my $line (<<"End_of_Property_List" =~ m{ \S .* \S }gx) { 

     L   Letter 
     Lu   Uppercase_Letter 
     Ll   Lowercase_Letter 
     Lt   Titlecase_Letter 
     Lm   Modifier_Letter 
     Lo   Other_Letter 

     M   Mark (combining characters, including diacritics) 
     Mn   Nonspacing_Mark 
     Mc   Spacing_Mark 
     Me   Enclosing_Mark 

     N   Number 
     Nd   Decimal_Number (also Digit) 
     Nl   Letter_Number 
     No   Other_Number 

     P   Punctuation 
     Pc   Connector_Punctuation 
     Pd   Dash_Punctuation 
     Ps   Open_Punctuation 
     Pe   Close_Punctuation 
     Pi   Initial_Punctuation (may behave like Ps or Pe depending on usage) 
     Pf   Final_Punctuation (may behave like Ps or Pe depending on usage) 
     Po   Other_Punctuation 

     S   Symbol 
     Sm   Math_Symbol 
     Sc   Currency_Symbol 
     Sk   Modifier_Symbol 
     So   Other_Symbol 

     Z   Separator 
     Zs   Space_Separator 
     Zl   Line_Separator 
     Zp   Paragraph_Separator 

     C   Other (means not L/N/P/S/Z) 
     Cc   Control (also Cntrl) 
     Cf   Format 
     Cs   Surrogate (not usable) 
     Co   Private_Use 
     Cn   Unassigned 

End_of_Property_List 

      my($short_prop, $long_prop) = $line =~ m{ 
       \b 
       (\p{Lu} \p{Ll} ?) 
       \s + 
       (\p{Lu} [\p{L&}_] +) 
       \b 
      }x; 

      $Prop_Table{$short_prop} = $long_prop; 

    } 

} 

Ví dụ:

$ unicats book.txt 
2357232 Total 
2357199 ASCII 
    33 Unicode 

1604949 \pL Letter 
    74455 \p{Lu} Uppercase_Letter 
1530485 \p{Ll} Lowercase_Letter 
     9 \p{Lo} Other_Letter 
    10676 \pN Number 
    10676 \p{Nd} Decimal_Number 
    19679 \pS Symbol 
    10705 \p{Sm} Math_Symbol 
    8365 \p{Sc} Currency_Symbol 
    603 \p{Sk} Modifier_Symbol 
     6 \p{So} Other_Symbol 
111899 \pP Punctuation 
    2996 \p{Pc} Connector_Punctuation 
    6145 \p{Pd} Dash_Punctuation 
    11392 \p{Ps} Open_Punctuation 
    11371 \p{Pe} Close_Punctuation 
    79995 \p{Po} Other_Punctuation 
548529 \pZ Separator 
548529 \p{Zs} Space_Separator 
    61500 \pC Other 
    61500 \p{Cc} Control 
+0

Trông quá sạch sẽ cho ngọc trai :-) Cảm ơn bạn đã trả lời câu hỏi của tôi. – Hali

+0

@Hali, không phải là ngôn ngữ lập trình cho cleanliless, mà là lập trình viên. Bất kỳ lập trình viên tạo ra mã lộn xộn là một thằng ngốc và một mối đe dọa. – tchrist

Các vấn đề liên quan