2013-03-02 7 views
8

文字列データがPerlに格納されている方法の基本的な説明が見つかりません!そのすべてのドキュメントのように私はすでに何らかの理由でこれを知っていると仮定しています。私はencode()、decode()について知っています。生のバイトをPerlの "文字列"に読み込み、Perlを使わずにそれらを再び出力することができます。私はオープンモードについて知っています。また、Perlは文字列を格納するためにいくつかの中間形式を使用しなければならず、文字とバイナリのデータを区別することができます。これはどこに記載されていますか?とにかくPerlの文字列は一体何ですか?

同等の質問です。このperlを与えられた:

$x = decode($y); 

デコードからホワット?

文字列データ構造に、バイナリXOR文字データ(BTWはUnicodeのスーパーセット - )のフラグが必要です。しかし、私はそれがドキュメントに記載されているか、ここで確認/信用されていればそれを望みます。

+2

['perldoc perlguts'](http://perldoc.perl.org/perlguts.html)にはいくつかの情報があります。文字列は通常は魔法ではありません。彼らは時々そうであるように見えるだけです。 –

+0

ありがとうジョン、これまでのところ最高の答えです。 perlgutsは楽しいように聞こえる。そして私を信じてください。私は魔法を信じません。特にPerlに関してはそうです。 – spinkus

+0

[this](http://plosquare.blogspot.in/2009/04/viewing-internal-representation-of.html)も役に立ちました。 –

答えて

15

これは大きな質問です。調べるには、Devel::Peekを使用して実際に文字列(または他の変数)に何が格納されているのかを少し深めてみてください。

まず

$ 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 

を行うことができますASCII文字列で始まることができます

$ 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として正しく解釈していることがはっきり分かります。問題は、私は表現がより

$ 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はバイトで見て通常の文字列のように見え、あなたがUnicode文字としてそれらを意味することを知る方法がないエスケープ\x{}を使用してオクテットを与えていない場合上記のエスケープされたオクテットを入力したときとは異なります。今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{}エスケープを使用したときに入力した文字列と文字列が正しく内部的に表示されていることがわかりました。

実際の答えは、バイトから文字に「デコード」されていますが、Peekの出力が見えるときにはより意味をなさないと思います。

最後に、あなたはPerlがそう

$ 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 
+0

うわー、ありがとう!それは私に多くの仕事をもたらしました! – spinkus

+0

@downvoter、お世話になりますか? –

-2

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

+1

何から何に変身?内部表現とは何ですか?それが私の質問です。文字の内部表現は、Unicodeのいくつかのスーパーセットですか?これは私がhttp://perldoc.perl.org/Encode.html#DESCRIPTIONを読んだドキュメントのいくつかと一貫しています。いいよ。では、バイナリデータはどのように文字列に格納されますか? – spinkus

+0

これは実際にOPが尋ねたものには何も答えません。 – friedo

2

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

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

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

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

3

短い答えのように、utf8プラグマを使用してUTF8としてあなたのソースコードを見ることができます:それは混乱少し長め
です:違いは見えませんプログラマー。

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

データ自体とそのようなデータの表現は別物であり、混乱しないようにしてください。文字列は(概念的に)コードポイントのシーケンスですが、メモリ内のバイト配列として表され、encode dのときにはいくつかのバイトシーケンスとして表されます。文字列にバイナリデータを格納する場合は、コードポイントの番号をバイト値として再解釈し、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文字あたり1つの整数を取りません。

+0

私はあなたの区別にはそれほど意味がありません。それに基づいて、データにはエンコーディングがありません。情報だけがエンコーディングを持っています。ほとんどの人は* data *と* information *で同じことを意味します。目的や意味がないので、エンコーディングなしでは何の話もほとんどありません。 – Borodin

6

代わりに、Perlの文字列の内部形式は可変であり、文字列の内容に依存します。

perluniintroをご覧ください。

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

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

しかし、なぜあなたがこれを知る必要があるのだろうか。 CでXSエクステンションを書いていない限り、内部フォーマットは透過的であり、あなたには見えません。

+0

ありがとうございます。私は "文字列"の "文字列"のエンコーディングが透過的であることに同意します。私は、Perlが異なる扱いをするバイト列と文字列が、どちらも同じデータ型に格納されていることがわかります。主に私が求めていたことは、Perlがこれをどうやって行ったのかということです。答えがあります。 – spinkus

+0

Perlには「バイト列」というデータ型がありません。文字列は一連の文字です。どんな意味で「問題がある」のですか? – Borodin

+0

"基本的には、文字列にバイトまたは文字が含まれているかどうかを覚えておく必要があります" - @amon。 – spinkus

関連する問題