Oct 27, 2011

Windows の Perl でテキストファイルの文字コードを変換

2011年11月12日追記:ぽち*ぷ〜ちいさましいちびのツールたち unzip.pl untar.pl enc.pl に enc.pl についてもう少しだけ詳しく書きました。

父の Vista機に Strawberry Perl をインストールして Windows上で Perl を使っていると、ぽちの Linux機で書いた日本語のテキストファイルを読みたい場合があったりします。けれども、それぞれのファイルシステムで使われている日本語文字コードが異なると、文字コードを変換しないままでは文字化けしてしまう事があります。高機能なテキストエディタがインストールしてあれば、わざわざ文字コードを変換したりしなくても読めるのですが、父の Vista機にはテキストエディタはメモ帳しか入っていません。メモ帳は Windows で使われている CP932以外にも UTF-8 ならそのまま表示出来るのですけども、日本語のメールで使われている ISO-2022-JP や、古いUNIX/Linux で使われている EUC-JP は文字コードを変換しないと読めません。

ものぐさなぽちは、文字コードや改行コードを自分で指定するのがめんどくさいので、unzip.pluntar.pl の文字コード自動推測部分を流用して、こんなのを書いて楽をしています。

enc.pl

#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use Encode;
use Encode::UTF8Mac; # utf-8-mac は fオプションと tオプションでしか使えません。
use Encode::Guess qw/ euc-jp cp932 iso-2022-jp utf8 /; # 自動推測の対象
use Encode::Locale;
use Path::Class;
use Getopt::Std;

my %opts;
getopts('f:t:', \%opts);

@ARGV or die "Usage: enc.pl [-f encoding_name] [-t encoding_name] text_file\n";

foreach ( @ARGV ) {
    my $file = file $_;
    my $reader = $file->openr or die "Couldn't open $file for reading: $!\n";
    my $content = $file->slurp;
    $reader->close;

    rename $file, "$file.bak";
    my ( $from, $to );
    if ( $opts{ f } ) {
        $from = $opts{ f };
    } else {
        my $f_obj = Encode::Guess->guess( $content );
        ref $f_obj ? $from = $f_obj->name : die "Couldn't guess: $f_obj\n";
    }
    if ( $opts{ t } ) {
        $to = $opts{ t };
    } else { $to = 'locale_fs'; }
    $content = encode( $to, decode( $from, $content ) );
    $from =~ /cp932|iso-2022-jp/ and $content =~ s/\r\n/\n/g;
    $to =~ /cp932|iso-2022-jp/ and $content =~ s/\n/\r\n/g;

    my $writer = $file->openw or die "Couldn't open $file for writing: $!\n";
    $writer->print( $content );
    $writer->close;
}

exit;
C¥> perl enc.pl [-f エンコード名] [-t エンコード名] テキストファイル

基本的には fオプションや tオプションも無くても適切に変換します。変換前の文字コードの推測に失敗してエラーが出た時には fオプションで、変換後の文字コードをファイルシステムのロケールにしたくない場合には tオプションで文字コードを指定して下さい。

一応、Mac で使われてる UTF-8-MAC も扱えますけども、UTF-8 と UTF-8-MAC の判別が難しいので、自動推測の候補には入れていません。UTF-8-MAC を扱う場合にはオプションで指定して下さい。

Posted at 18:09 in perl | Comments/Trackbacks ()
Comments/Trackbacks
TrackBack ping me at
http://pochi.usamimi.info/blog/perl/enc.
Post a comment

writeback message: