18 December 2010

(Perl) 波ダッシュ(〜)を全角チルダ(~)に変換する

MacOSやLinuxで入力した 「〜」 (波ダッシュ wave dash)は、Windowsでは文字化けしたり、汚いフォントで表示されるようだ。

Unicode標準化で日本人の”協力度合い”が低かったので、日本語のフォントがなおざりにされた結果だとか…

Wikipedia の『波ダッシュ』記事に詳しく書かれている。

さて、ガラパゴス言語である日本語に対応させるため、LinuxやMacで入力したテキストを、Windows対応する必要がある場合もある。その時に、世界標準の「波ダッシュ」を「全角チルダ」に変換するスクリプト(赤色に着色したところ)

任意のエンコード形式から、任意のエンコード形式へ変換する機能も付けといた (緑色に着色したところ)


#!/usr/bin/perl

use warnings;
use strict;
use utf8;
use Encode::Guess qw/euc-jp shiftjis iso-2022-jp/;

my $output_encode = 'utf8'; # 出力時のエンコード
my $flag_conv_wavedash = 0; # 波ダッシュ(U+301C)を全角チルダ(U+FF5E)に変換

print("\nfile encode changer\n\n");

# ファイル名のユーザ入力
print 'input filename : ';
$_ = <STDIN>;
chomp;
unless(-f $_){ die "pogram aborted : file not found ($_)\n"; }

# ファイルから、改行を無視して、一気に読み込む
open(FH, "<$_") or die("program aborted : file open error ($_)\n");
my $strAllLines = undef;
{
local $/ = undef; # 改行を区切りとして使わない
$strAllLines = <FH>;
}
close(FH);

my $input_encode = '';
my $enc = Encode::Guess->guess($strAllLines);

if(ref($enc) eq 'Encode::utf8'){ $input_encode = 'utf8'; }
elsif(ref($enc) eq 'Encode::Unicode'){
$input_encode = $$enc{'Name'};
}
elsif(ref($enc) eq 'Encode::XS'){
$input_encode = $enc->mime_name();
}
elsif(ref($enc) eq 'Encode::JP::JIS7'){
$input_encode = $$enc{'Name'};
}
else{
# 二つ以上のエンコードが推定される場合は、$encに文字列が返る
die("program aborted : unknown encode (".$enc.")\n");
}

print("input file encode is $input_encode\n\n");

# 変換先のエンコード形式をユーザ入力
printf("Select output encode\n 1.utf8\n 2.shiftjis (cp932)\n 3.iso-2022-jp (jis)\n".
" 4.euc-jp\n 5.utf-16\n 6.utf-32\n 1/2/3/4/5/6 ? : ");
$_ = <STDIN>;
chomp;
if(length($_)<=0){ die("select error\n"); }
elsif(uc($_) eq '1'){ $output_encode = 'utf8'; }
elsif(uc($_) eq '2'){ $output_encode = 'shiftjis'; }
elsif(uc($_) eq '3'){ $output_encode = 'iso-2022-jp'; }
elsif(uc($_) eq '4'){ $output_encode = 'euc-jp'; }
elsif(uc($_) eq '5'){ $output_encode = 'UTF-16'; }
elsif(uc($_) eq '6'){ $output_encode = 'UTF-32'; }
else { die("program aborted : selection is not correct\n"); }

# 波ダッシュ(〜)変換モードの決定
print("convert japanese 'wave dash' to 'full width tilde' for Windows compatible (Y/N) [N] : ");
$_ = <STDIN>;
chomp();
if(uc($_) eq 'Y'){ $flag_conv_wavedash = 1; }
elsif(uc($_) eq 'N' || length($_)<=0){ $flag_conv_wavedash = 0; }
else{ die("program aborted : invalid imput\n"); }

# 出力ファイルのユーザ入力
print 'output filename : ';
$_ = <STDIN>;
chomp;
if(-e $_ && !(-w $_)){ die "program aborted : file is not writable ($_)\n"; }


print("converting ($input_encode -> $output_encode) ...\n");

# ファイルに書き込む
open(FH, ">$_") or die("program aborted : file open error ($_)\n");
$strAllLines = $enc->decode($strAllLines); # input encode → utf8

# 波ダッシュ変換 301C→FF5E
my $ch_wavedash = pack('U',0x301c);
my $ch_fullwidthtilde = pack('U',0xff5e);
if($flag_conv_wavedash == 1){ $strAllLines =~ s/$ch_wavedash/$ch_fullwidthtilde/g; }


print(FH Encode::encode($output_encode, $strAllLines)); # utf8 → output encode
close(FH);

print("conversion succeed !\n");