4

スクリプトの先頭に次のブロックがあります。

#!/usr/bin/perl5 -w
use strict;
binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");
binmode(STDERR, ":utf8");

一部のサブルーチンでは、(離れたサブルーチンからの) 他のエンコーディングがある場合、キリル文字やその他の文字を受信すると、データが正しく表示されません。問題を引き起こすのは「binmode」です。

サブルーチンのみで、binmode utf8 をローカルで「オフ」にすることはできますか?

グローバル binmode 設定を削除できず、リモート エンコーディングを変更できません。

4

3 に答える 3

7

これを実現する 1 つの方法は、STDハンドルを「複製」し、複製されたファイルハンドルが:rawレイヤーを使用するように設定し、それをハンドルのローカル バージョンに割り当てることSTDです。たとえば、次のコード

binmode(STDOUT, ':utf8');
print(join(', ', PerlIO::get_layers(STDOUT)), "\n");

{
    open(my $duped, '>&', STDOUT);
    # The ':raw' argument could also be omitted.
    binmode($duped, ':raw');
    local *STDOUT = $duped;
    print(join(', ', PerlIO::get_layers(STDOUT)), "\n");
    close($duped);
}

print(join(', ', PerlIO::get_layers(STDOUT)), "\n");

版画

unix, perlio, utf8
unix, perlio
unix, perlio, utf8

私のシステムで。

于 2015-01-06T15:49:03.813 に答える
3

@nwellnhof のアプローチが好きです。Unicode と ASCII だけを扱う - ごく少数の人が楽しむ贅沢 - 私の本能は、バイトをそのままにして、必要なときに選択的に利用することEncodeですdecode()/encode()。問題のあるデータソースを特定できる場合はdecode、それらを処理するときにフィルター/挿入できます。

% file koi8r.txt 
koi8r.txt: ISO-8859 text
% cat koi8r.txt 
������ �� ����� � ������� ���. ���
���� ����� ������ ����� �����.
% perl -CO -MEncode="encode,decode" -E 'say decode("koi8-r", <>) ;' koi8r.txt
Американские суда находятся в международных водах. Япония
于 2015-01-06T18:43:04.467 に答える