2015-08-11 17 views
6

Yerel dil ASCII karakterleri Unicode karakterlere (Tamil) dönüştürmek için bir Perl programı yazıyorum. Dosyaya yazdırma, bir dosyaya yazdırmaya karşı kaplamak için Perl

Bu

Değişmeze process_file yılında benim program

#!/bin/perl 
use strict; 
use warnings; 

use open ':std'; 
use open ':encoding(UTF-8)'; 

use Encode qw(encode decode); 
use Data::Dump qw(dump); 
use Getopt::Long qw(GetOptions); 

Getopt::Long::Configure qw(gnu_getopt); 

my $font; 
my %map; 
GetOptions(
    'font|f=s' => \$font, 
    'help|h' => \&usage, 
) or die "Try $0 -h for help"; 

print "Do you want to map $font? (y/n)"; 
chomp(my $answer = lc <STDIN>); 

$font = lc($font); 
$font =~ s/ /_/; 
$font =~ s/(.*?)\.ttf/$1/; 

if ($answer eq "y") { 
    map_font(); 
} 
else { 
    restore_map(); 
} 

foreach (@ARGV) { 

    my $modfile = "$_"; 

    $modfile =~ s/.*\/(.*)/uni$1/; 

    process_file($_, $modfile); 
} 

sub process_file { 

    my @options = @_; 

    open my $source, '<', "$options[0]"; 
    my $result = $options[1]; 
    my $test = "./text"; 
    my $missingchar = join("|", map(quotemeta, sort { length $b <=> length $a } keys %map)); 

    while (<$source>) { 
     $/ = undef; 
     s/h;/u;/g;  #Might need change based on the tamil font 
     s/N(.)/$1N/g; #Might need change based on the tamil font 
     s/n(.)/$1n/g; #Might need change based on the font 
     s/($missingchar)/$map{$1}/g; 

     print "$_"; 

     open my $final, '>:utf8', "$result"; 
     print $final "$_"; 
     close $final; 
    } 
} 

sub map_font { 

    my @oddhexes = qw/0B95 0B99 0B9A 0B9E 0B9F 0BA3 0BA4 0BA8 0BAA 0BAE 0BAF 0BB0 0BB2 0BB5 0BB3 0BB4 0BB1 0BA9/; 
    my @missingletters = qw/0BC1 0BC2/; 
    my @rest = qw/0B85 0B86 0B87 0B88 0B89 0B8A 0B8E 0B8F 0B90 0B92 0B93 0B83 0BBE 0BBF 0BC0 0BC6 0BC7 0BC8 0BCD 0B9C 0BB7 0BB8 0BB9 0BCB 0BCA 0BCC/; 

    foreach (@oddhexes) { 

     my $oddhex = $_; 

     $_ = encode('utf8', chr(hex($_))); 
     print "Press the key for $_ :"; 
     chomp(my $bole = <STDIN>); 
     if ($bole eq "") { 
      next; 
     } 

     $map{$bole} = $_; 

     foreach (@missingletters) { 

      my $oddchar = encode('utf8', chr(hex($oddhex)) . chr(hex($_))); 

      print "Press the key for $oddchar :"; 
      chomp(my $missingchar = <STDIN>); 
      if ($missingchar eq "") { 
       next 
      } 

      $map{$missingchar} = $oddchar; 
     } 

    } 

    foreach (@rest) { 

     $_ = encode('utf8', chr(hex($_))); 

     print "Press the key for $_ :"; 
     chomp(my $misc = <STDIN>); 
     if ($misc eq "") { 
      next 
     } 

     $map{$misc} = $_; 
    } 

    open my $OUTPUT, '>', $font || die "can't open file"; 
    print $OUTPUT dump(\%map); 
    close $OUTPUT; 
} 

sub restore_map { 

    open my $in, '<', "$font" || die "can't open file: $!"; 

    { 
     local $/; 
     %map = %{ eval <$in> }; 
    } 

    close $in; 
} 

sub usage { 
    print "\nUsage: $0 [options] {file1.txt file2.txt..} \neg: $0 -f TamilBible.ttf chapter.txt\n\nOptions:\n -f --font - used to pass font name\n -h --help - Prints help\n\nManual mapping of font is essential for using this program\n"; 
    exit; 
} 

, terminal içinde print "$_"; görüntüler düzgün Tamil Unicode karakterleri çıkışıdır. Bununla birlikte, output to the file handle$final çok farklıdır.

%map, here'dir.

Neden çıktılar farklı?

Bu davranışı nasıl düzeltebilirim?

Bu question'u gördüm ancak bu aynı değil. Benim durumumda, filehandle çıkışı farklıyken terminal doğru sonucu görüntüler.

open my $final, '>:utf8', "$result"; 

+0

Gitmelisiniz * ifade değiştirici * kullanmayı düşünün * gibi bir sonraki "eğer $ misc eq" "' yerine "if ($ misc eq" ") {next}' – Borodin

+0

@Borodin İpucu için teşekkürler. Ben kodu –

+0

ASCII ne anlama düşüncelerinizi anlamına gelmez değiştirecektir. –

cevap

9

Sizin açık ifadesi karakterleri beklemek ve çıkarken daha sonra UTF-8 dizileri içine kodlamak için dosya tanıtıcısı ayarlar. Ama bu o bayt Perl IO aksine

yeniden karakter olarak işlenir ve kodlanmış neden olur %map karma gelen bayt dizileri önceden kodlanmış gönderiyor, uçbiriminiz UTF-8-kodlanmış beklemek ayarlanır veri, ama STDOUT hiç bir kodlama (use open ':std' kendi başına bir etkisi yoktur, aşağıya bakınız) yapmak ayarlı değil bu yüzden terminali beklediğini olur ki değişmeden aracılığıyla UTF-8 kodlu bayt geçer

Bu arada,

ile :encoding(UTF-8) varsayılan açık modunu ayarladınız

fakat open numaralı çağrıya çağrılarınızda geçersiz kılın. :utf8 modu, geniş karakterlerden bayt dizilerine çok basit bir çeviri yapar, ancak :encoding(UTF-8) çok daha kullanışlıdır çünkü yazdırılan her karakterin geçerli bir Unicode değeri olduğunu kontrol eder. Orada böyle bir hata yakalanmış olurdu iyi bir şans olduğunu ve varsayılan izin ve sadece

open my $final, '>', $result; 

temiz ve düzenli olması için, programınız karakterden içinde çalışması gerekir yazmak için daha iyi olurdu bu karakterler ekleyerek tüm yeni açılan dosya için varsayılan kodlama olarak UTF-8 ayarlayabilirsiniz

kolları yanı sıra STDIN ve STDOUT basılır zaman ve dosya kolları UTF-8'e bu karakterleri kodlamak için ayarlanmalıdır

programın üstüne 0

(:encoding(utf-8):utf8 tercih edilir) ve encode için tüm aramaları kaldırın.Sen neredeyse sağ vardı, ama :std ve :encoding(utf-8) ihtiyaç

adresten de

use utf8; 

eklemek gerekir aynı use açıklamada olmak çok üst programda UTF-8 karakterleri kullanabilmek için kendisi

Ayrıca birkaç tesadüfi hatalar var. Açıklamada Örneğin

  • için

    open my $in, '<', "$font" || die "can't open file: $!"; 
    

    buna bir nesne olur sürece $font gibi tek sayıl değişken alıntı neredeyse her zaman yanlış olduğunu ve stringification yöntemi çağırmak istiyorum

    || yerine or'a ihtiyacınız var, aksi halde yalnızca $font

    numaralı telefonun gerçeklerini test ediyorsunuz

    Ben $in adında bir değişken Sana kararsız olacağını düşünüyorum içerebilir neyi sorsam; $in_fh iyidir ve

    Bu hesaba tüm bu alarak $!

    den nedenle yanı sıra die dizeye dosyanın adını koymak her zaman güzeldir ifadenizi yapan yaygın bir deyimdir Sen büyük ve küçük harfler skaler değişkenler arasındaki tutarlı olmalıdır bu

    open my $in_fh, '<', $font or die qq{Unable to open "$font" for input: $!}; 
    
  • benziyor, ve küçük harf doğru seçimdir. Yani

    open my $OUTPUT, '>', $font || die "can't open file"; 
    

    open my $out_fh, '>', $font or die qq{Unable to open "$font" for output: $!}; 
    
  • çizgi gibi bir şey olmalıdır

    $/ = undef; 
    

    aksi takdirde kalıcı kalanı için giriş kayıt ayırıcısını değiştiriyorsanız, başka yerde kullanmış olduğu local $/ olmalıdır Programınızın ve modüllerin. Programınız while döngünün bir sonraki tekrarında sonra dosyanın geri kalanı tamamını okumak ve bir satır işlemek ve böylece aynı zamanda, dosya sapından sonraki ilk okuma görünür

+0

Çok teşekkür ederim !! Sen de merak ettiğim diğer her şeyi işaret ettin. –

+1

@OneFace: Harika. Bunu 'kodlama' çağrıları olmadan çalışmayı başardınız mı? – Borodin

+0

Şu anda Kodu yeniden kontrol ediyorum.Yazı tipini, ': std: encoding (utf-8) 'kullanırken karakterlerin değerleri çok farklı olduğundan yeniden haritalamam gerekiyor. Hala çeşitli seçenekler ekleyerek programı genişletiyorum. Tekrar haritalandırdığımda sonucu yayınlayacağım. Şu an yatak zamanı. Son derece değerli yardımlar için bir kez daha teşekkür ederim! –