perl:標準Moduleで漢字変換

[Index]
 ●標準Moduleを使ってみよう
  ◆PODからModuleを探す
  ◆use文でModuleを指定
  ◆デフォルトインポート
 ●漢字コード変換の検討
  ◆perlのversionによる漢字変換機能の違い
  ◆EncodeのPODを読む
  ◆Encodeによる変換の例
 ●htmlconv.plへの実装


●標準Moduleを使ってみよう

 ・Perlの本当の魅力とは、Perl環境をインストールする「だけ」で山のようについてく
  る標準Module群にあるのではないかと思っています。
 
 ・そこで、以前CVSのネタとして出した「htmlconv.pl」に、標準Moduleによる漢字変換
  機能を付加してみたいと思います。
 
 ・Perlで標準Moduleを使用する際、最初に頭に置くことは以下の3点です。
    * PODで探す
    * use文でModuleを指定
    * デフォルトインポート
    

 ◆PODからModuleを探す
 
  + 始めに目的のModuleを探すために、POD(Perl Old Document)で使えそうなModule
   をピックアップします。
 
  + PODはPerlのModule/文法/その他諸々に関する記述が全て載っています。PODはそれ
   自身が簡単なマークアップ言語ですが、PerlのDistribution内に含まれるツールに
   よって、いろいろな形式に変換して閲覧することができます。
 
  + 例えば、Win32版のperl v5.8.0のパッケージでは、Install後にHTML形式のPODがメ
   ニューとして用意されます。
 
  + 実際のところは、Internet等で情報を集め、使用するModuleのあたりを付けたとこ
   ろで、PODから詳細情報を引き出すのが普通でしょう。PODは英語ですから(*1)。


 ◆use文でModuleを指定

  + Moduleは関数又はクラスの集まりです。Moduleの使用を宣言することで、Moduleが
   持つ関数やクラスをプログラムから利用することが可能となります。
 
  + Module使用の宣言には2種類あります。
    require()関数を使用する方法
    use文を使用する方法
 
  + 後者(use文)はperl5から導入された方法ですが、こちらが一般的になりつつあると
   のことです。


 ◆デフォルトインポート

  + あるModule、例えば「Sample」があったとします。そしてSampleには A, B, C 3種
   類の関数が含まれているとします。
   
    +-- Module Sample --+
    |   :       |
    | sub A { ... }   |
    | sub B { ... }   |
    | sub C { ... }   |
    |   :       |
    +-------------------+
  
  + このとき、use Sample; とすれば、A, B, Cを使えるでしょうか。答えは「使えると
   は限りません」。それはSampleの書き方によります。
 
  + 関数にはインポート(*2)という考え方があります。例えば A はデフォルトインポー
   トでB, C は違う場合、use Sample; では、Aのみが使用できます。
 
    +-- Module Sample -------------------------+
    |   :                  |
    | @EXPORT  = qw(A);  # Default Export  |
    | @EXPORT_OK = qw(B C); # Export On Demand |
    |                     |
    | sub A { ... }              |
    | sub B { ... }              |
    | sub C { ... }              |
    |   :                  |
    +------------------------------------------+

  + B, C も使用したい場合、Module使用宣言時に、インポートしたい関数をリストで列
   挙します。
     (例) use Sample qw(A B C);
 
  + デフォルトインポートか否かについては、PODに記述されています。PODからuse文記
   述の内容を判断することになります。
 
  + それでは漢字変換を例にして、標準Moduleを使用してみます。


●漢字コード変換の検討

 ◆perlのversionによる漢字変換機能の違い
 
  + perl v5.6.0までは、jcode.pl/jcode.pmを使用する必要がありました。しかし
   perl v5.8.0では標準Distributionに含まれるModule「Encode」で、jcodeの機能を
   実現することができます。
  
  + Encodeでは日本語だけでなく、様々な言語を扱うことができるので、これからプロ
   グラムを書くのであれば、やはりEncodeモジュールを使用すべきでしょう。
 
 
 ◆EncodeのPODを読む
 
  + EncodeについてPODを見ると以下のような記述があります。(抜粋)
  
   +----------------------------------------------------------------------+
   | NAME                                 |
   |   Encode - character encodings                   |
   | SYNOPSIS                               |
   |   use Encode;                           |
   |     :                              |
   |     :                              |
   | TERMINOLOGY                             |
   |  * *character*: a character in the range 0..(2**32-1) (or more).  |
   |   (What Perl's strings are made of.)                |
   |     :                              |
   |  * *octet*: 8 bits of data, with ordinal values 0..255 (Term for  |
   |   bytes passed to or from a non-Perl context, e.g. a disk file.)  |
   |     :                              |
   |     :                              |
   | PERL ENCODING API                          |
   |   $octets = encode(ENCODING, $string [, CHECK])          |
   |     :                              |
   |   For example, to convert a string from Perl's internal format to |
   |   iso-8859-1 (also known as Latin1),               |
   |    $octets = encode("iso-8859-1", $string);           |
   |     :                              |
   |   $string = decode(ENCODING, $octets [, CHECK])          |
   |     :                              |
   |   For example, to convert ISO-8859-1 data to a string in Perl's  |
   |   internal format:                        |
   |    $string = decode("iso-8859-1", $octets);           |
   |     :                              |
   |     :                              |
   |   [$length =] from_to($octets, FROM_ENC, TO_ENC [, CHECK])     |
   |     :                              |
   |   For example, to convert ISO-8859-1 data to Microsoft's CP1250  |
   |   encoding:                            |
   |    from_to($octets, "iso-8859-1", "cp1250");           |
   |     :                              |
   |     :                              |
   +----------------------------------------------------------------------+
  
  + この文章を見ると、どうやら、ある漢字コードの文字列データ(byte:8bit並び)を
   perlの内部処理用コードに置き換えるのが「decode」、perlの内部処理用コードか
   らある漢字コードの文字列に置き換えるのが「encode」ということになります。
  
  + PODをもう少し読み進めると「decode後はutfのフラグが云々」という記述があるの
   で、perlの内部処理用コードとは、恐らくUTF-8(unicode)をベースにしたものだと
   考えらます。(同じわけではないという記述もありました)
   
   
 ◆Encodeによる変換の例
   
  + これまでの情報から、encode, decodeのAPIを使ってコード変換を行う例は、以下の
   ようになります。
   
   +------------------------------------------------------------------------+
   | #!/usr/bin/perl -w                           |
   | #shiftjisからeucへ変換してみます                    |
   |                                    |
   | use strict;                              |
   | use Encode qw(encode decode);                     |
   |                                    |
   | my $octet_pre;                             |
   | my $octet_post;                            |
   | my $string_perl;                            |
   |                                    |
   | while(<>) {                              |
   |   $octet_pre = $_; # 冗長ですが理解のために             |
   |                                    |
   |   $string_perl = decode("shiftjis", $octet_pre); # shiftjisの文字列を|
   |                          # perl処理用データへ|
   |                                    |
   |   $octet_post = encode("euc-jp", $string_perl); # perl処理用データを|
   |                          # eucの文字列へ   |
   |   print $octet_post;                         |
   | }                                   |
   +------------------------------------------------------------------------+
  
  + ただし、これはプログラムのソースコードを書く環境がunicodeであるという前提が
   あると思われます。ちょっと強引な説明ですが、decodeでunicode化し、何らかの処
   理を加えて、出力時に所望のコードへ変換するという考え方なのでしょう。
  
  + しかし、我々の場合はほとんどが、ShiftJIS又はEUC等の環境でソースコードを記述
   するので「単に変換」する方が楽です。この場合はfrom_toを使用します。

   +----------------------------------------+
   | #!/usr/bin/perl -w           |
   | #shiftjisからeucへ変換してみます    |
   |                    |
   | use strict;              |
   | use Encode qw(from_to);        |
   |                    |
   | while(<>) {              |
   |   from_to("shiftjis", "euc-jp", $_); |
   |   print;               |
   | }                   |
   +----------------------------------------+
  
  + 尚、漢字コードを表す文字列(例の中の"euc-jp"等)は、Encode::JPのPODにリストが
   記述されています。
   
   +--------------------------------+
   | shiftjis  : Shift JIS    |
   | iso-2022-jp : JIS       |
   | euc-jp   : EUC       |
   | utf8    : UTF-8 / Unicode |
   |  :              |
   +--------------------------------+


●htmlconv.plへの実装

 ・これらの機能を使用し、htmlconv.plに漢字変換機能を実装しました。
 
 ・ソースコードはShiftJISで記述しているため、内部で文字列処理をする場合は、一度
  ShiftJISに置き換え、最後の出力時に所望の漢字コードへ変換しています。
  
 ・今は、各内部ルーチンに出力を分担させているため、漢字コード変換によりコード追
  加個所も複数となってしまいました。これについて今後は、メモリに貯めてから出す
  際に変換する形へ変えていきたいと思います。(リファクタリングになる?)
 
 ・本レポートのまとめとして、この後に機能追加後のhtmlconv.plの説明テキストを添
  付します。
 

(*1)プログラミング、コンピュータ関連に限らず、エンジニアリングにおいて英語の資料
  が読めないというのは、学生ならともかく社会人(プロのエンジニア)は許してもらえ
  ない雰囲気になりつつありますよね(Y_Y)。

(*2)Moduleを使う側から見れば「インポート(import)」ですが、Module内のリソースを使
  わせる側から見れば「エクスポート(export)」になります。


/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
↓ここからhtmconv.plの説明テキストです↓

+------------------------------------------+
| 今回のVersion(v2003_07_27)のダウンロード |
+------------------------------------------+

[Index]
 ●本スクリプトの目的と特徴
 ●動作環境
 ●使用方法
 ●カスタマイズ
 ●今後の予定
 ●免責について
 ●著作権、利用について
 ●作成履歴

+===============================================================+
| テキスト→HTMLコンバータ Perlスクリプト            |
| htmlconv.pl                          |
| Coded by Monpe                        |
+---------------------------------------------------------------+
| Revision Date                         |
| * 2003/07/02 : Special Func. Implement : First Release Rev. |
| * 2003/07/07 : Add Kanji Code Option            |
| * v2003_07_27 : Add Kanji Code Convert Option        |
+===============================================================+

●本スクリプトの目的と特徴

 ・htmlconv.plは、txtファイルをhtmlファイルへ変換するPerlスクリプトです。以下の
  2点を特徴とします。
   ----------------------------------------------------------------------
   (1)オリジナルtxtファイルと全く同じ体裁でhtml変換を行います。
   (2)指定文字列で始まる行を「Index行」と見なし、自動で目次を作成します。
   ----------------------------------------------------------------------
 
 ・例えば、空白インデントに意味のあるファイル、プログラムのソースコードをhtml
  変換するケース等を想定しています。(変換結果:添付のhtmlconv.html)

   (例) // SampleはC++のコードですが
      #include <iostream>
      using namespace std;
     
      int main() {
        cout << "Hello World" << endl;
        return 0;
      }

  
 ・その他、下記のようにASCIIキャラとスペースで記述した簡易図を含むテキストファ
  イルの変換にも威力を発揮します。(変換結果:添付のhtmlconv.html)

   (例)┌──┐ 32 ┌───┐  32
     │CPU ┝━/━┥North ┝┳━/━> PCI_BUS
     └──┘   │Bridge│┃ 32
            └───┘┣━/━> MEM
                 ┃ 32 ┌───┐  16
                 ┗━/━┥South ├┬─/─> IDE
                    │Bridge││ 16
                    └───┘└─/─> Multi_I/O

   * ただしunicode(UTF-8)化した場合は、体裁が崩れ(ずっこけ)ます。(_o_)


●動作環境
 
 ・Version v2003_07_27以降では、perl v5.8.0以上で動作します。漢字変換機能は、
  perl v5.8.0標準Distributionに含まれるEncodeモジュールで実現しています。
  
   (1)perl v5.8.0 build 806
   ~~~~~~~~~~~~~~~~~~~~~~~~
    + 2002/07/18にReleaseされたperl v5.8.0は直接日本語を扱えるようです。
    
    + 以下のURLより各環境(Windows/Solaris/Linux)のbinary packageを入手可能。
      http://www.activestate.com/Products/ActivePerl/


●使用方法

 ・htmlconv.pl Source_Text_File <Kanji_Code_To> <Kanji_Code_From>
  <オプションの意味>
   * Source_Text_File : 変換元テキストファイル
   * Kanji_Code_To  : HTML変換後の漢字コード(省略可能)
   * Kanji_Code_From : HTML変換前テキストファイルの漢字コード(省略可能)
              + Kanji_Code_From指定時は、Kanji_Code_To省略不可
 
 ・変換結果は標準出力(普通は画面)へ送られます。ファイル化したい場合はOSのリダイ
  レクト機能を利用して下さい。
  
 ・漢字コードオプションでは以下を指定できます。未指定時(デフォルト)はShiftJISに
  なります。
    shiftjis : ShiftJIS
    jis   : JIS
    euc   : EUC
    utf   : UTF-8 (unicode)
 
 ・オプションを交えた使用例を示します。
 
   (例1) テキストファイルをHTML化
       htmlconv.pl sample_sjis.txt > sample_sjis.html
        + この場合、漢字コードは何も指定していないので
          ShiftJIS→ShiftJIS
         として処理される
   
   (例2) ShiftJISのテキストを、JISとしてHTML化
       htmlconv.pl sample_sjis.txt jis > sample_jis.html
        + 変換後の漢字コードにjisを指定
        + 変換前の漢字コードShiftJISなので省略可能
   
   (例3) JISのテキストを、EUCとしてHTML化
       htmlconv.pl sample_jis.txt euc jis > sample_euc.html
        + 変換後の漢字コードにeucを指定(省略不可)
        + 返還前の漢字コードにjisを指定(省略不可)

 
 ・尚、添付の「htmlconv.html」は、このファイル(htmlconv.txt)をhtmlconv.plで変換
  した結果です。
 
 ※Perlスクリプトの一般的な起動方法については説明を省きます。perlのセットアップ
  に関するドキュメントを参照下さい。


●カスタマイズ

 ・スクリプト内のグローバル変数を変更することで付加機能カスタマイズが可能です。
  主な付加機能は以下の2種です。
   (1)インデックス文字列修飾指定
   (2)インデックス作成
 
 ・Perlスクリプトをある程度触れる方向けの機能なので、敢えてここでの詳細説明は省
  きます。スクリプト内のコメントを参照の上変更して下さい。


●今後の予定

 ・今作者自身がこのスクリプトに感じている不満は、主に以下の4点です。
 
   (1)漢字コードがShiftJIS固定 (2003.07.07版で追加)
     --> このテキストを書いているうちに気が付きました。アホなので最優先で直し
       たい。
     --> デフォルトはShiftJIS, コマンドラインオプションで他のコードを指定する
       ようにしたいと思います。
    
     ★ さらに考えてみると、漢字コードが指定できるのに変換はしないというのも
      不自然なので、変換機能を追加しました。(v2003_07_27版より)
    

   (2)TABの変換
     --> 現在は規定の全角スペースに変換しているが、これだとTABで表構成してい
       るテキストが崩れてしまう。
     --> 今後はタブを含む文字列の解析をし、最適なスペースへ置換する機能を実装
       する。
  
   (3)Indexジャンプ機能が無い
     --> 今はインデックスが記述されているだけで、HTMLの特徴であるリンクが活用
       できていない。
     --> 作成したインデックスに自動でラベル付加し、ジャンプ機能を持たせる。
  
   (4)http: ftp:のURLへのリンク作成機能が無い
     --> HTMLにURLが記述されているのにリンクしてないのはすごく不自然。
     --> http://, ftp://, @マークを見て判断し、hrefタグの付加を行う。

 ・これらの不満点(他にもあるのですが)は、今後徐々に改善していく予定です。また修
  飾タグをスタイルシートへ移行することも予定の一つです。


●免責について

 ・本スクリプト(htmlconv.pl)を使用したことにより生じた全ての結果について、作者
  (Monpe)は責を負いません。
 
 ・また本スクリプト(htmlconv.pl)の推奨環境構築で生じた全ての結果についても、作者
  (Monpe)は責を負いません。
 

●著作権、利用について

 ・本スクリプト(htmlconv.pl)及び説明用ドキュメント(htmlconv.txt, htmlconv.html)
  の著作権は作者(Monpe)が保有します。(念のため書いておきます。著作権主張する価
  値は無いコードですけど。)
 
 ・免責と著作権に関する項目に同意頂ける限り、本スクリプトの利用/改変/配布は自由
  です。


●作成履歴

 2003.06.26 : プロトタイプ版
 2003.07.02 : リリース版
 2003.07.07 : 漢字コードオプション追加
 2003.07.27 : 漢字コード変換機能追加

[END]

[▲Perl Home▲]