2010-11-13 8 views
6

J'ai un fichier texte créé en utilisant un logiciel OCR - d'environ un mégaoctet. Certains caractères inhabituels apparaissent partout dans le document et la plupart d'entre eux sont des erreurs OCR. Je voudrais trouver tous les caractères utilisés dans le document pour détecter facilement les erreurs (comme la commande UNIQ mais pour les caractères, pas pour les lignes).Comment rassembler les statistiques d'utilisation des caractères dans un fichier texte en utilisant des commandes Unix?

Je suis sur Ubuntu. Quelle commande UNIX devrais-je utiliser pour afficher tous les caractères utilisés dans un fichier texte?

Répondre

8

Cela devrait faire ce que vous cherchez:

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

La prémisse est que le sed met chaque caractère dans le fichier sur une ligne par lui-même, la séquence habituelle sort | uniq -c bandes tout sauf l'un des chaque caractère unique qui se produit, et fournit des comptes de combien de fois chacun s'est produit.

En outre, vous pouvez ajouter | sort -n à la fin de la séquence entière pour trier la sortie du nombre de fois où chaque caractère s'est produit. Exemple:

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

Je suis venu ici pour poster exactement cela. Mais hélas je suis trop lent. Mais voici un indice utile. A la fin, si vous voulez tout sur une ligne, vous pouvez ajouter "| perl -pe 'chomp'" – OmnipotentEntity

+0

Merci beaucoup. C'est exactement ce que je cherchais. Propre et simple – Hali

0

En ce qui concerne l'utilisation des commandes * nix, la réponse ci-dessus est bon, mais il ne reçoit pas les statistiques d'utilisation.

Cependant, si vous voulez réellement des statistiques (comme la plus rare utilisée, médiane, la plus utilisée, etc) sur le fichier, ce Python devrait le faire.

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

Mais il y a aussi des statistiques dans les réponses ci-dessus. Merci de répondre à ma question. – Hali

+0

@Hali - N'a pas vu l'édition ci-dessus (Et la réponse a besoin d'un morceau de Python de toute façon;) – new123456

1

Cela fera:

#!/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 sur lui-même, ce programme produit:

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

Si vous voulez le caractère littéral et/ou le nom du personnage, aussi, c'est facile à ajouter.

Si vous voulez quelque chose de plus sophistiqué, ce programme calcule les caractères par propriété Unicode. Cela peut suffire à vos besoins, et sinon, vous devriez être capable de l'adapter.

#!/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; 

    } 

} 

Par exemple:

$ 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

On dirait trop propre pour perle :-) Merci d'avoir répondu à ma question. – Hali

+0

@Hali, juge pas le langage de programmation pour cleanliless, mais le programmeur. Tout programmeur qui génère du code désordonné est un idiot et une menace. – tchrist

Questions connexes