Created
March 11, 2026 00:07
-
-
Save zr-tex8r/77b0135da958fa10ff339e7df3096467 to your computer and use it in GitHub Desktop.
例のアレ🍣
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #### 失敗するパターン | |
| use strict; | |
| use File::Temp; | |
| use Cwd; | |
| use Encode; | |
| use Encode::Locale; # console_inはcp932だと仮定する | |
| # STDINからの文字列読込と等価な処理 | |
| # ※入力文字列はASCII文字からなるとする | |
| # ※console_inはASCII互換な文字コードとする | |
| my $arch = Encode::decode('console_in', 'windows'); # ASCII列/UTF8フラグON | |
| my $pkg = 'foo'; # ASCII列/UTF-8フラグOFF | |
| my $cwd = Cwd::getcwd(); # CP932バイト列/UTF8フラグOFF | |
| my $temp = File::Temp::tempdir("$cwd/tempXXXX"); # CP932バイト列/UTF8フラグOFF | |
| END { rmdir($temp); } | |
| # これはフラグOFFの文字列だけ連結している | |
| my $path1 = "$temp/$pkg.tar.xz"; # CP932バイト列/UTF8フラグOFF | |
| system("echo", $path1); | |
| # これは想定通り | |
| # $archがフラグONなので全体がフラグONになる | |
| my $path2 = "$temp/$pkg.$arch.tar.xz"; # CP932バイト列/UTF8フラグON | |
| # 意味的にはバイト列だがフラグONなので内部表現がUTF-8のバイト列になっている | |
| # (例えば"あ"(0x82A0)は"C2 82 C2 A0"となっている) | |
| # system()で実際にOSに渡されるのは内部表現のバイト列である:-( | |
| system("echo", "$temp/$pkg.$arch.tar.xz"); | |
| # これは文字化けする |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #### 姑息な修正方法 | |
| use strict; | |
| use File::Temp; | |
| use Cwd; | |
| use Encode; | |
| use Encode::Locale; # console_inはcp932だと仮定する | |
| # STDINからの文字列読込と等価な処理 | |
| # ※入力文字列はASCII文字からなるとする | |
| # ※console_inはASCII互換な文字コードとする | |
| my $arch = Encode::decode('console_in', 'windows'); # ASCII列/UTF8フラグON | |
| utf8::downgrade($arch, 1); # フラグOFFの文字列に変換する | |
| my $pkg = 'foo'; # ASCII列/UTF-8フラグOFF | |
| my $cwd = Cwd::getcwd(); # CP932バイト列/UTF8フラグOFF | |
| my $temp = File::Temp::tempdir("$cwd/tempXXXX"); # CP932バイト列/UTF8フラグOFF | |
| END { rmdir($temp); } | |
| # これはフラグOFFの文字列だけ連結している | |
| my $path1 = "$temp/$pkg.tar.xz"; # CP932バイト列/UTF8フラグOFF | |
| system("echo", $path1); | |
| # これは想定通り | |
| # これもフラグOFFの文字列だけ連結している | |
| my $path2 = "$temp/$pkg.$arch.tar.xz"; # CP932バイト列/UTF8フラグOFF | |
| system("echo", "$temp/$pkg.$arch.tar.xz"); | |
| # 想定通り |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #### マトモな修正方法 | |
| # ("保持するデータはバイト列でなく文字列とする"の原則に従う) | |
| use strict; | |
| use File::Temp; | |
| use Cwd; | |
| use Encode; | |
| use Encode::Locale; | |
| # STDINからの文字列読込と等価な処理 | |
| # ※入力文字列はASCII文字でなくてもOK | |
| my $arch = Encode::decode('console_in', 'windows'); # Unicode文字列/UTF8フラグON | |
| my $pkg = 'foo'; # ASCII列/UTF-8フラグOFF | |
| my $cwd = Encode::decode('locale_fs', Cwd::getcwd()); # Unicode文字列/UTF8フラグON | |
| my $temp = Encode::decode('locale_fs', File::Temp::tempdir(Encode::encode('locale_fs', "$cwd/tempXXXX"))); # Unicode文字列/UTF-8フラグON | |
| END { rmdir(Encode::encode('locale_fs', $temp)); } | |
| my $path1 = "$temp/$pkg.tar.xz"; # Unicode文字列/UTF8フラグON | |
| # ※Encode::encodeは必ずフラグOFFの値を返す | |
| system("echo", Encode::encode('locale_fs', $path1)); | |
| # (もちろん実際はechoじゃなくてパス名を引数にとるコマンドとする) | |
| # これは想定通り | |
| my $path2 = "$temp/$pkg.$arch.tar.xz"; # Unicode文字列/UTF8フラグON | |
| system("echo", Encode::encode('locale_fs', $path2)); | |
| # 想定通り |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
system()やrmdir()等のOS関連の機能において文字列を実効的に「その内部表現のバイト列」として扱うのが全ての現況 😣$archは意味的にUnicode文字列であるため、このプログラムでは確かに「文字列とバイト列の連結」をやっていることになるのだが、しかしASCIIしか含まない文字列は「ASCIIのバイト列」とも「CP932のバイト列」とも見なせるので、その前提であれば問題ないはず。