2015-08-29 15 views
6

ich mit einem großen Wörterbuch auf einem Android-Wortspiel arbeite -‚Wide-Zeichen in Unterprogramm Eintrag“ - UTF-8 kodierten kyrillisch Worte als Folge von Bytes

app screenshot

Die Worte (über 700 000) Als separate Zeilen in einer Textdatei gespeichert (und dann in eine SQLite - Datenbank geschrieben)

Um Konkurrenten davon abzuhalten, mein Wörterbuch zu extrahieren, möchte ich alle Wörter codieren, die länger als 3 Zeichen mit MD5 sind (I verschleiern Sie keine kurzen Wörter und Wörter mit seltenen russischen Buchstaben ъ und э, denn ich würde gerne aufzählen sie in meiner App).

So, hier ist mein Skript, das ich versuche, mit perl v5.18.2 auf Mac Yosemite zu laufen:

#!/usr/bin/perl -w 

use strict; 
use utf8; 
use Digest::MD5 qw(md5_hex); 

binmode(STDIN, ":utf8"); 
#binmode(STDOUT, ":raw"); 
binmode(STDOUT, ":utf8"); 

while(<>) { 
     chomp; 
     next if length($_) < 2; # ignore 1 letter junk 
     next if /жы/;   # impossible combination in Russian 
     next if /шы/;   # impossible combination in Russian 

     s/ё/е/g; 

     #print "ORIGINAL WORD $_\tENCODED WORD: "; 

     if (length($_) <= 3 || /ъ/ || /э/) { # do not obfuscate short words 
       print "$_\n";    # and words with rare letters 
       next; 
     } 

     print md5_hex($_) . "\n";   # this line crashes 
} 

Wie Sie sehen können, habe ich zu kyrillischen Buchstaben in den Quellcode meiner Perl verwenden Skript - deshalb habe ich use utf8; auf seine Oberseite gesetzt.

Allerdings ist mein echtes Problem, dass length($_) meldet zu hohe Werte (wahrscheinlich die Anzahl der Bytes anstelle der Anzahl der Zeichen).

Also habe ich versucht, und fügte hinzu:

binmode(STDOUT, ":raw"); 

oder:

binmode(STDOUT, ":utf8"); 

Aber das Skript stirbt dann mit Breitzeichen in Unterprogramm Eintrag an der Linie mit print md5_hex($_).

Bitte helfen Sie mir mein Skript zu reparieren.

Ich betreibe es als:

perl ./generate-md5.pl <words.txt> encoded.txt 

und hier ist Beispiel words.txt Daten für Ihre Bequemlichkeit:

а 
аб 
абв 
абвг 
абвгд 
съемка 

Antwort

9

md5_hex eine Reihe von Bytes für die Eingabe erwartet, aber du bist Übergabe einer decodierten Zeichenfolge (eine Folge von Unicode-Code-Punkten). Explizit die Zeichenfolge codieren.

use strict; 
use utf8; 
use Digest::MD5; 
use Encode; 
... 
# $_ is assumed to be utf8 encoded without check 
print Digest::MD5::md5_hex(Encode::encode_utf8($_)),"\n"; 
# Conversion only when required: 
print Digest::MD5::md5_hex(utf8::is_utf8($_) ? Encode::encode_utf8($_) : $_),"\n"; 
+0

Dank 'md5_hex()' in der Tat verursacht den Absturz. Ich habe diesen Teil in [Perldoc Digest :: MD5] übersehen (http://search.cpan.org/dist/Digest-MD5/MD5.pm) –

+1

Perfekt! Ich hatte ein ähnliches Problem mit base64 Konvertieren von kyrillischen (und anderen) Buchstaben, außer Latein. Ich habe es gerade hinzugefügt und es funktioniert wie ein Zauber! Danke und @AlexanderFarber! – Arsenii

2

mein eigentliches Problem ist, dass Länge ($ _) berichtet, zu hohe Werte

Ja, Sie lesen aus dem ARGV Datei-Handle und haben nicht festgelegt seine Codierung auf UTF-8

Sie können das Pragma open verwenden, um dies zu beheben.Statt alle Ihre binmode Aussagen,

verwenden
use open qw/ :std :encoding(utf8) /; 

, die den Standard-Öffnungsmodus für alle Handles ändern, einschließlich dem Standard, an :encoding(utf8)