10

私は(遅れて)初めてUnicodeの水域をテストしていますが、アラビア語の文字列をエンコードしてからデコードするプロセスが、単語を構成する個々の文字を分離する効果がある理由を理解できていません。

以下の例では、「ﻟﻠﺒﻴﻊ」という単語は、右から左に書かれた 5 つの個別の文字で構成されています。周囲の文脈(隣接する文字)に応じて、文字は形を変えます


use strict;
use warnings;
use utf8;

binmode( STDOUT, ':utf8' );

use Encode qw< encode decode >;

my $str = 'ﻟﻠﺒﻴﻊ';                 # "For sale" 
my $enc = encode( 'UTF-8', $str );
my $dec = decode( 'UTF-8', $enc );

my $decoded = pack 'U0W*', map +ord, split //, $enc;

print "Original string : $str\n";     #  ل ل ب ي ع   
print "Decoded string 1: $dec\n"      #  ل ل ب ي ع
print "Decoded string 2: $decoded\n"; #  ل ل ب ي ع

追加情報

  • この投稿に文字列を貼り付けると、レンダリングが反転するため、「ﻊﻴﺒﻠﻟ」のようになります。「正しく」見えるように手動で反転しています。正しい 16 進ダンプを以下に示します。

    $ echo "ﻟﻠﺒﻴﻊ" | hexdump
    0000000 bbef ef8a b4bb baef ef92 a0bb bbef 0a9f
    0000010
    
  • Perl スクリプトの出力 (池上の要求による):

    $ perl unicode.pl | od -t x1
    0000000 4f 72 69 67 69 6e 61 6c 20 73 74 72 69 6e 67 20
    0000020 3a 20 d8 b9 d9 8a d8 a8 d9 84 d9 84 0a 44 65 63
    0000040 6f 64 65 64 20 73 74 72 69 6e 67 20 31 3a 20 d8
    0000060 b9 d9 8a d8 a8 d9 84 d9 84 0a 44 65 63 6f 64 65
    0000100 64 20 73 74 72 69 6e 67 20 32 3a 20 d8 b9 d9 8a
    0000120 d8 a8 d9 84 d9 84 0a
    0000127
    

    そして、私が印刷した場合$str

    $ perl unicode.pl | od -t x1
    0000000 4f 72 69 67 69 6e 61 6c 20 73 74 72 69 6e 67 20
    0000020 3a 20 d8 b9 d9 8a d8 a8 d9 84 d9 84 0a
    0000035
    

    最後に(池上のリクエストによる):

    $ grep 'For sale' unicode.pl | od -t x1
    0000000 6d 79 20 24 73 74 72 20 3d 20 27 d8 b9 d9 8a d8
    0000020 a8 d9 84 d9 84 27 3b 20 20 23 20 22 46 6f 72 20
    0000040 73 61 6c 65 22 20 0a
    0000047
    
  • パールの詳細

    $ perl -v
    
    This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi
    (with 53 registered patches, see perl -V for more detail)
    
  • ファイルへの出力は文字列を逆にします: "ﻊﻴﺒﻠﻟ"


質問

私はいくつか持っている:

  • 印刷中に各文字のコンテキストを維持するにはどうすればよいですか?

  • 「処理」されていないにもかかわらず、元の文字列が個々の文字として画面に出力されるのはなぜですか?

  • ファイルに出力すると、単語が逆になります (これは、スクリプトの右から左への性質によるものだと思います)。これを防ぐ方法はありますか?

  • 次のことが成り立たないのはなぜですか。$str !~ /\P{Bidi_Class: Right_To_Left}/;

4

2 に答える 2

3
  • StackOverflow によって返されるソース コード (を使用して取得wget):

    ... ef bb 9f ef bb a0 ef ba 92 ef bb b4 ef bb 8a ...
    
    U+FEDF ARABIC LETTER LAM INITIAL FORM
    U+FEE0 ARABIC LETTER LAM MEDIAL FORM
    U+FE92 ARABIC LETTER BEH MEDIAL FORM
    U+FEF4 ARABIC LETTER YEH MEDIAL FORM
    U+FECA ARABIC LETTER AIN FINAL FORM
    
  • perlStackOverflow によって返されたソース コードから取得した出力:

    ... ef bb 9f ef bb a0 ef ba 92 ef bb b4 ef bb 8a 0a
    ... ef bb 9f ef bb a0 ef ba 92 ef bb b4 ef bb 8a 0a
    ... ef bb 9f ef bb a0 ef ba 92 ef bb b4 ef bb 8a 0a
    
    U+FEDF ARABIC LETTER LAM INITIAL FORM
    U+FEE0 ARABIC LETTER LAM MEDIAL FORM
    U+FE92 ARABIC LETTER BEH MEDIAL FORM
    U+FEF4 ARABIC LETTER YEH MEDIAL FORM
    U+FECA ARABIC LETTER AIN FINAL FORM
    U+000A LINE FEED
    

    したがって、ソースにあるものを正確に取得できます。

  • perlあなたが得た出力:

    ... d8 b9 d9 8a d8 a8 d9 84 d9 84 0a
    ... d8 b9 d9 8a d8 a8 d9 84 d9 84 0a
    ... d8 b9 d9 8a d8 a8 d9 84 d9 84 0a
    
    U+0639 ARABIC LETTER AIN
    U+064A ARABIC LETTER YEH
    U+0628 ARABIC LETTER BEH
    U+0644 ARABIC LETTER LAM
    U+0644 ARABIC LETTER LAM
    U+000A LINE FEED
    

    さて、バグのある Perl (アラビア文字のみを反転して変更するもの) を使用することもできますが、ソースに含まれていると思われる機能が含まれていない可能性がはるかに高くなります。ソースを形成するバイトを確認する必要があります。

  • echoあなたが得た出力:

    ef bb 8a ef bb b4 ef ba 92 ef bb a0 ef bb 9f 0a
    
    U+FECA ARABIC LETTER AIN FINAL FORM
    U+FEF4 ARABIC LETTER YEH MEDIAL FORM
    U+FE92 ARABIC LETTER BEH MEDIAL FORM
    U+FEE0 ARABIC LETTER LAM MEDIAL FORM
    U+FEDF ARABIC LETTER LAM INITIAL FORM
    U+000A LINE FEED
    

    perlから得たものと から得たものには大きな違いがあるechoため、それらが異なって表示されるのは当然のことです。


以下を使用して検査された出力:

$ perl -Mcharnames=:full -MEncode=decode_utf8 -E'
   say sprintf("U+%04X %s", $_, charnames::viacode($_))
      for unpack "C*", decode_utf8 pack "H*", $ARGV[0] =~ s/\s//gr;
' '...'

( のバイトを交換することを忘れないでくださいhexdump。)

于 2013-01-31T07:57:37.237 に答える
1

多分あなたの殻に何か奇妙なことがありますか?出力をファイルにリダイレクトすると、結果は同じになります。これを試してみてください:

use strict;
use warnings;
use utf8;

binmode( STDOUT, ':utf8' );

use Encode qw< encode decode >;

my $str = 'ﻟﻠﺒﻴﻊ';                 # "For sale" 
my $enc = encode( 'UTF-8', $str );
my $dec = decode( 'UTF-8', $enc );

my $decoded = pack 'U0W*', map +ord, split //, $enc;

open(F1,'>',"origiinal.txt") or die;
open(F2,'>',"decoded.txt") or die;
open(F3,'>',"decoded2.txt") or die;

binmode(F1, ':utf8');binmode(F2, ':utf8');binmode(F3, ':utf8');

print F1 "$str\n";     #  ل ل ب ي ع   
print F2 "$dec\n";     #  ل ل ب ي ع
print F3 "$decoded\n";
于 2013-01-31T08:55:55.467 に答える