ibmのas400(現在の製品名は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 [テストテスト]->[テスト テスト ] [テストテスト]->[ テスト テスト] [テストテストテスト]->[テスト テスト テスト]