2011-05-05 20 views
5

मेरे पास एक पंक्ति/शब्द प्रत्येक पंक्ति है जिसमें मैंने एसटीडीआईएन से पर्ल को पढ़ा है। मेरे पास स्टॉपवर्ड की एक सूची है (जैसे "á", "साओ", "é") और मैं प्रत्येक शब्द के साथ उनमें से प्रत्येक की तुलना करना चाहता हूं, और अगर वे बराबर हैं तो हटा दें। समस्या यह है कि मैं फ़ाइल के एन्कोडिंग प्रारूप के बारे में निश्चित नहीं हूं।पर्ल - फ़ाइल एन्कोडिंग और शब्द तुलना

मैं file आदेश से मिलता है:

words.txt: Non-ISO extended-ASCII English text 

मेरे linux टर्मिनल UTF-8 में है और यह कुछ शब्दों के लिए सही सामग्री से पता चलता है और दूसरों को नहीं करने के लिए। उनमें से कुछ से उत्पादन होता है:

condi<E3> 
conte<FA>dos 
ajuda, mas não resolve 
mo<E7>ambique 
pedagógico são fenómenos 

आप देख सकते हैं कि 3 और 5 वीं लाइनों को सही ढंग से उच्चारण और विशेष वर्णों के साथ शब्दों की पहचान कर रहे हैं, जबकि दूसरों को नहीं। अन्य लाइनों के लिए सही आउटपुट होना चाहिए: condiã, conteúdos और moçambique।

यदि मैं binmode(STDOUT, utf8) का उपयोग करता हूं तो "गलत" रेखाएं अब सही तरीके से आउटपुट करती हैं जबकि अन्य लोग नहीं करते हैं। उदाहरण के लिए 3 पंक्ति:

ajuda, मास nà £ o संकल्प

क्या मैं लोगों को क्या करना चाहिए?

उत्तर

3

यह इस तरह काम करता है:

C:\Dev\Perl :: chcp 
Aktive Codepage: 1252. 

C:\Dev\Perl :: type mixed-encoding.txt 
eins zwei drei Käse vier fünf Wurst 
eins zwei drei Käse vier fünf Wurst 

C:\Dev\Perl :: perl mixed-encoding.pl < mixed-encoding.txt 
eins zwei drei vier fünf 
eins zwei drei vier fünf 

कहाँ mixed-encoding.pl इस प्रकार है: स्क्रिप्ट को UTF-8 में एन्कोड करने की जरूरत नहीं है

use strict; 
use warnings; 
use utf8; # source in UTF-8 
use Encode 'decode_utf8'; 
use List::MoreUtils 'any'; 

my @stopwords = qw(Käse Wurst); 

while (<>) { # read octets 
    chomp; 
    my @tokens; 
    for (split /\s+/) { 
     # Try UTF-8 first. If that fails, assume legacy Latin-1. 
     my $token = eval { decode_utf8 $_, Encode::FB_CROAK }; 
     $token = $_ if [email protected]; 
     push @tokens, $token unless any { $token eq $_ } @stopwords; 
    } 
    print "@tokens\n"; 
} 

ध्यान दें कि। यह सिर्फ इसलिए है कि यदि आपके स्क्रिप्ट में फंकी चरित्र डेटा है तो आपको एन्कोडिंग मैचों को सुनिश्चित करना होगा, इसलिए use utf8 यदि आपका एन्कोडिंग यूटीएफ -8 है, और यदि ऐसा नहीं है।

अद्यतन tchrist की ध्वनि सलाह के आधार पर:

use strict; 
use warnings; 
# source in Latin1 
use Encode 'decode'; 
use List::MoreUtils 'any'; 

my @stopwords = qw(Käse Wurst); 

while (<>) { # read octets 
     chomp; 
     my @tokens; 
     for (split /\s+/) { 
       # Try UTF-8 first. If that fails, assume 8-bit encoding. 
       my $token = eval { decode utf8 => $_, Encode::FB_CROAK }; 
       $token = decode Windows1252 => $_, Encode::FB_CROAK if [email protected]; 
       push @tokens, uc $token unless any { $token eq $_ } @stopwords; 
     } 
     print "@tokens\n"; 
} 
+0

@michael धन्यवाद अब इसे सही ढंग से outputting है;) मैंने महसूस किया कि फ़ाइल के बहुमत ISO-8859-1 में है और utf-8 में कुछ भागों (यही कारण है कि उनमें से कुछ सही ढंग से outputting गया है) एक और चीज़। मुझे 'lc' फ़ंक्शन का उपयोग करना होगा क्योंकि मेरे स्टॉपवर्ड सभी कम-से-कम हैं, और वाक्यांशों में utf-8 नहीं होने पर मुझे समस्याएं आ रही हैं। इस परिस्थितियों में यदि मेरे पास एक उच्चारण के साथ एक ऊपरी केस पत्र है तो यह कम cased नहीं होगा। – Barata

+2

@ बाराटा: यदि आप 'uc' आदि पर काम करना चाहते हैं तो आपको अभी भी गैर-यूटीएफ 8 तारों को डीकोड करना होगा। पर्ल 5.12 (और ऊपर) 'यूनिकोड_स्ट्रिंग्स सुविधा भी मदद कर सकती है, जिसमें यह बाइट स्ट्रिंग के लिए आईएसओ 885 9 -1 मान लेगा। तुलना करें: 'perl -e' प्रिंट uc ("\ xB5 \ xE9 \ xDF") ''=> ' μéß', ** जो गलत है, ** 'perl -M5.012 -e' प्रिंट uc ("\ xB5 \ xE9 \ xDF") ''=>' ΜÉSS' ** जो सही है। ** अंतिम स्ट्रिंग वास्तव में '" \ x {39C} \ x {C9} SS "' या '" \ N { ग्रीक कैपिटल लिटर एमयू} \ N {लेटिन कैपिटल लिटर ई ACUTE} एसएस "'। मूल स्ट्रिंग '\ N {माइक्रो साइन} \ N {लेटिन छोटे अक्षर ई के साथ} \ N {लैटिन लघु पत्र SHARP एस}" 'है। – tchrist

+0

@tchrist माइकल कोड का उपयोग करके, 'if $ @' की जांच करना और स्ट्रिंग को आईएसओ -885 9 -1 में डीकोड करना पर्याप्त है? – Barata

4

मैं दृढ़ता से आप एक ऐसा फ़िल्टर मिश्रित एनकोडिंग में लाइनों के साथ एक फ़ाइल लेता है और उन्हें शुद्ध UTF-8 के लिए अनुवाद बनाने की सलाह। तो बजाय

open(INPUT, "< badstuff.txt") || die "open failed: $!"; 

आप फिक्सर से या तो निश्चित संस्करण, या एक पाइप खोलता था, जैसे:

open(INPUT, "fixit < badstuff.txt |") || die "open failed: $!" 

या तो घटना में, आप तो

binmode(INPUT, ":encoding(UTF-8)") || die "binmode failed"; 

फिर fixit होगा कार्यक्रम बस यह कर सकता है:

use strict; 
use warnings; 
use Encode qw(decode FB_CROAK); 

binmode(STDIN, ":raw") || die "can't binmode STDIN"; 
binmode(STDOUT, ":utf8") || die "can't binmode STDOUT"; 

while (my $line = <STDIN>) { 
    $line = eval { decode("UTF-8", $line, FB_CROAK() }; 
    if ([email protected]) { 
     $line = decode("CP1252", $line, FB_CROAK()); # no eval{}! 
    } 
    $line =~ s/\R\z/\n/; # fix raw mode reads 
    print STDOUT $line;  
} 

close(STDIN) || die "can't close STDIN: $!"; 
close(STDOUT) || die "can't close STDOUT: $!"; 
exit 0; 

देखें कि यह कैसे काम करता है? बेशक, आप इसे किसी अन्य एन्कोडिंग में डिफ़ॉल्ट रूप से बदल सकते हैं, या कई फॉल बैक हैं। शायद @ARGV में उनकी सूची लेना सबसे अच्छा होगा।

+0

यूटीएफ -8 से डीकोडिंग करते समय एक विशिष्ट एन्कोडिंग से डीकोड करने के लिए बहुत अच्छा बिंदु विफल रहता है। तो आप यूनिकोड और विरासत तारों के मिश्रण के साथ खत्म नहीं होते हैं, लेकिन यूनिकोड में सबकुछ homogenize। – Lumi

संबंधित मुद्दे