9

文字列データがPerlに保存される方法の基本的な説明が見つかりません!すべてのドキュメントのように、私は何らかの理由でこれをすでに知っていると想定しています。私はencode()、decode()について知っており、生のバイトをPerlの「文字列」に読み込んで、Perlがねじ込むことなく再度出力できることを知っています。私はオープンモードについて知っています。また、Perlは文字列を格納するためにいくつかの内部形式を使用する必要があり、文字データとバイナリデータを区別できることを収集します。これはどこに文書化されていますか?

同等の質問は; このperlを考えると:

$x = decode($y);

何に、何からデコードしますか?

私が理解できる限り、文字列データ構造には、これがバイナリXOR文字データ(ところでUnicodeのスーパーセットである内部形式の)であることを示すフラグが必要です-http ://perldoc.perl.org/Encode.html #DESCRIPTION)。しかし、それがドキュメントに記載されているか、ここで確認/信用されていない場合は、それを希望します。

4

5 に答える 5

18

これは素晴らしい質問です。調査するために、 Devel :: Peekを使用して、文字列(または他の変数)に実際に何が格納されているかを確認することで、もう少し深く掘り下げることができます。

まず、ASCII文字列から始めましょう

$ perl -MDevel::Peek -E 'Dump "string"'
SV = PV(0x9688158) at 0x969ac30
  REFCNT = 1
  FLAGS = (POK,READONLY,pPOK)
  PV = 0x969ea20 "string"\0
  CUR = 6
  LEN = 12

次に、Unicode IOレイヤーをオンにして、同じことを行うことができます

$ perl -MDevel::Peek -CSAD -E 'Dump "string"'
SV = PV(0x9eea178) at 0x9efcce0
  REFCNT = 1
  FLAGS = (POK,READONLY,pPOK)
  PV = 0x9f0faf8 "string"\0
  CUR = 6
  LEN = 12

そこから、いくつかのワイド文字を手動で追加してみましょう

$ perl -MDevel::Peek -CSAD -e 'Dump "string \x{2665}"'
SV = PV(0x9be1148) at 0x9bf3c08
  REFCNT = 1
  FLAGS = (POK,READONLY,pPOK,UTF8)
  PV = 0x9bf7178 "string \342\231\245"\0 [UTF8 "string \x{2665}"]
  CUR = 10
  LEN = 12

このことから、Perlがこれをutf8として正しく解釈していることがはっきりとわかります。問題は、エスケープを使用してオクテットを指定しない場合\x{}、表現が通常の文字列のように見えることです。

$ perl -MDevel::Peek -CSAD -E 'Dump "string ♥"'
SV = PV(0x9143058) at 0x9155cd0
  REFCNT = 1
  FLAGS = (POK,READONLY,pPOK)
  PV = 0x9168af8 "string \342\231\245"\0
  CUR = 10
  LEN = 12

上記のエスケープされたオクテットを入力したときとは異なり、Perlが認識するのはバイトだけであり、それらがユニコード文字であることを意味することを知る方法はありません。ではdecode、何が起こるかを使って見てみましょう

$ perl -MDevel::Peek -CSAD -MEncode=decode -E 'Dump decode "utf8", "string ♥"'
SV = PV(0x8681100) at 0x8683068
  REFCNT = 1
  FLAGS = (TEMP,POK,pPOK,UTF8)
  PV = 0x869dbf0 "string \342\231\245"\0 [UTF8 "string \x{2665}"]
  CUR = 10
  LEN = 12

\x{}TADA !、これで、エスケープを使用したときに入力したものと一致する文字列が内部的に正しく表現されていることがわかります。

実際の答えは、バイトから文字への「デコード」ですが、Peekの出力を見るともっと理にかなっていると思います。

utf8最後に、プラグマを使用して、Perlにソースコードをutf8として認識させることができます。

$ perl -MDevel::Peek -CSAD -Mutf8 -E 'Dump "string ♥"'
SV = PV(0x8781170) at 0x8793d00
  REFCNT = 1
  FLAGS = (POK,READONLY,pPOK,UTF8)
  PV = 0x87973b8 "string \342\231\245"\0 [UTF8 "string \x{2665}"]
  CUR = 10
  LEN = 12
于 2013-03-02T06:04:25.947 に答える
6

スカラー変数の流動的な文字列/数値ステータスのように、Perlの文字列の内部形式は可変であり、文字列の内容に依存します。

perluniintroこれを言う、を見てください。

内部的には、Perlは現在、プラットフォームのネイティブ8ビット文字セット(たとえば、Latin-1)がデフォルトでUTF-8であるものを使用して、Unicode文字列をエンコードします。具体的には、文字列内のすべてのコードポイントが0xFF以下の場合、Perlはネイティブの8ビット文字セットを使用します。それ以外の場合は、UTF-8を使用します。

つまり、のような文字列"I have £ two"は(bytes)として格納されますI have \x{A3} two。(ポンド記号はです。)ここで、 -笑顔のU+00A3ようなマルチバイトのUnicode文字列を追加すると、Perlは新しい文字を追加する前に文字列全体をUTF-8に変換し、(bytes)を与えます。この最後の文字を再度削除すると、文字列UTF-8がエンコードされたままになります。U+263AI have \xC2\xA3 two\xE2\x98\xBA`I have \xC2\xA3 two

しかし、なぜあなたはこれを知る必要があるのだろうか。XS拡張機能をCで記述していない限り、内部形式は透過的で見えません。

于 2013-03-02T06:21:43.300 に答える
2

簡単な答え:それは混乱です
少し長いです:違いはプログラマーには見えません。

基本的に、文字列にバイトまたは文字が含まれているかどうかを覚えておく必要があります。文字はユニコードコードポイントです。ASCIIにしか遭遇しない場合、違いは目に見えず、危険です。

データ自体とそのようなデータの表現は別個のものであり、混同しないでください。文字列は(概念的には)コードポイントのシーケンスですが、メモリ内ではバイト配列として表され、encodedの場合はバイトシーケンスとして表されます。バイナリデータを文字列に格納する場合は、コードポイントの数をバイト値として再解釈し、0〜255のコードポイントに制限します。

(たとえば、ファイルにはエンコードがありません。そのファイル内の情報にはエンコードがあります(文字レベルではASCII、UTF-16、またはEBCDIC、アプリケーションレベルではPerl、HTML、または.ini))

文字列の正確な格納形式は関係ありませんが、そのような文字列内に完全な整数を格納できます。

# this will work if your perl was compiled with large integers
my $string = chr 2**64; # this is so not unicode
say ord $string; # 18446744073709551615

内部フォーマットは、そのような値に対応するように適宜調整されます。通常の文字列は、文字ごとに1つの整数を使用しません。

于 2013-03-02T06:20:59.877 に答える
2

Perlの内部文字列形式は実装に依存しますが、通常はUtF-8のスーパーセットです。文字列を内部フォーマットと他のエンコーディングに変換するためにデコードとエンコードを使用するため、それが何であるかは問題ではありません。

デコードはperls内部形式に変換し、エンコードはperls内部形式から変換します。

バイナリデータは、文字0〜255と同じ方法で内部的に保存されます。

エンコードとデコードは、フォーマット間で変換するだけです。たとえば、UTF8エンコーディングは、各文字がperl文字vlaues 0〜255を使用するオクテットのみになることを意味します。つまり、文字列はUTF8オクテットで構成されます。

于 2013-03-02T06:03:24.163 に答える
-2

PerlはUnicodeよりも多くを処理できるため、非常に柔軟性があります。時々、できないものとインターフェースしたいので、encode(...)とdecode(...)を使用してそれらの変換を処理できます。http://perldoc.perl.org/utf8.htmlを参照してください

于 2013-03-02T05:15:33.313 に答える