end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

ebcdic->sjis変換で失われたシフト文字分の空白をEncode::CJKConstantsで復活

ibmas400(現在の製品名はSystem i)で使用されるebcdicという文字コードでは全角文字がある場合、その前後にシフト文字(0E:シフトアウト,0F:シフトイン)が挿入されます。


例えば、「漢字」という全角2文字がある場合

1byte 2-5byte 4byte
0E 漢字 0F

as400とのファイル交換にhulftを使用すると、先ほどのシフト文字を半角スペースに置換してくれますが、シフト文字が半角スペースに置換されずに桁ずれを起こしてしまったデータをよく見かけます。

ebcdic)テスト テスト テスト
  sjis)テストテストテスト #←半角スペース2文字分ずれてます

Encode::CJKConstantsでは、各エンコーディング文字コードの範囲が定義されていますが、これを利用して、ebcdic->sjis変換で失われたシフト文字分の空白を復活させることができます。

Encode::CJKConstantsの抜粋

our %RE = (
    ASCII     => '[\x00-\x7f]',
    BIN       => '[\x00-\x06\x7f\xff]',
    EUC_0212  => '\x8f[\xa1-\xfe][\xa1-\xfe]',
    EUC_C     => '[\xa1-\xfe][\xa1-\xfe]',
    EUC_KANA  => '\x8e[\xa1-\xdf]',
    JIS_0208  => "$_0208{1978}|$_0208{1983}|$_0208{1990}",
    JIS_0212  => "\e" . '\$\(D',
    ISO_ASC   => "\e" . '\([BJ]',
    JIS_KANA  => "\e" . '\(I',
    '2022_KR' => "\e" . '\$\)C',
    SJIS_C    => '[\x81-\x9f\xe0-\xfc][\x40-\x7e\x80-\xfc]',
    SJIS_KANA => '[\xa1-\xdf]',
    UTF8      => '[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf]'
);
#!c:/Perl/bin/perl
use strict;
use warnings;
use Encode::CJKConstants;

sub main {

    my @strs = ('テストテスト','テストテスト','テストテストテスト');
    for my $org_str ( @strs ){
	my $str = $org_str;
	#連続する全角文字の前後に半角スペースを挿入
	$str =~ s/((?:$Encode::CJKConstants::RE{SJIS_C})+)/ $1 /go;
	print "[$org_str]->[$str]\n";
    }
}

main();

実行結果

endo@a4 /cygdrive/c/home/endo/tmp
$ ./foo2.pl 
[テストテスト]->[テスト テスト ]
[テストテスト]->[ テスト テスト]
[テストテストテスト]->[テスト テスト テスト]

そもそも、このようなことをしなくても、iconv等できちんとebcdic->sjis変換してくれればいいんですけどね。