PDIC Toolkit Tutorial - Step 3

Step 3 で書かれていることを実際にやってみるには、PDIC Toolkit Ver. 1.13 以降が必要です。
操作例の中で、[ENTER] と書かれた部分は、キーボードの [Enter] キーを押すことを意味します。
xyzzy のキー操作の説明では、次のような記述法を用います。
a[A] キーを打つ
C-x[Ctrl] キーを押しながら [X] キーを打つ
C-x C-f  [Ctrl] キーを押しながら [X] キーを打ち、さらに [Ctrl] キーを押しながら [F] キーを打つ。
C-x k[Ctrl] キーを押しながら [X] キーを打ち、さらに [Ctrl] キーを離した状態で [K] キーを打つ。
M-x[Alt] キーを押しながら [X] キーを打つ。
F12[F12] キーを打つ。

はじめに

STEP 3 では、PDIC 辞書ファイルから一定の条件を満たす項目だけを抜き出して、Unicode 形式のプレーンテキストファイルまたは XML ファイルに保存する方法を説明します。

抜き出す項目の条件を記述するために、ごく簡単なプログラミングをする必要があります。そのため、まず xyzzy という奇妙な名前のテキストエディタについて説明します。期限なしで無料で使えるこのソフトウェアは Unicode 形式のファイルを扱える上に、Perl スクリプト * を直接実行できるので便利です。これ以外にも優れたテキストエディタは存在しますが、今後はこのソフトウェアの使用を前提に説明を続けます。

* 別のプログラムによって解釈され実行されるプログラムを「スクリプト」と呼びます。Perl 用に書かれたプログラムは、実行のたびに Perl によって解釈されます。その対概念である「コンパイルされたプログラム」は、プロセッサ(例えば C プログラムの場合)または仮想マシーン(例えば Java プログラムの場合)によって実行されます。

はじめての xyzzy

ダウンロード&インストール

xyzzy はインプレス社「窓の杜」の xyzzy からダウンロードできます。xyzzy には特別なインストーラーはありません。Lzh 形式の圧縮ファイルを適当なフォルダ(例えば、C:¥Program Files)に解凍するだけです。

[スタート] ボタンから xyzzy を実行できるようにする手順は、次の通りです。

準備作業 (1) - 環境変数 XYZZYHOME の設定

環境変数 XYZZYHOME に、xyzzy で書く文書やスクリプトを保存するフォルダを指定します。例として C:¥home を指定する手順を次に示します。

  1. Windows 95/98/Me の場合
  2. Windows 2000 の場合

準備作業 (2) - .xyzzy の作成

.xyzzy はキー配列などを設定するためのファイルです。おそらく標準のキー配列のままでは Windows ユーザーには使いにくいので、とりあえず私が作った .xyzzy をダウンロードして使ってみることをお勧めします。.xyzzy の上で右クリックして [対象をファイルに保存] を選び、C:¥home に保存してください。

基本概念と画面構成

xyzzy で表示・編集するテキストの一つ一つはバッファと呼ばれる仮想的な入れ物に収められています。

バッファはファイルとは異なる概念です。私たちは「ファイルを編集する」と簡単に言いますが、正確にはファイルを直接編集するわけではありません。ファイルの内容をバッファに読み込み、編集し、バッファの内容をファイルに保存する、という一連の作業を通じて、ファイルの中身を変更しています。

上図の A の部分にバッファの一覧が表示されています。バッファの名前の書かれたタブをクリックすることで、バッファの内容を B の領域に表示し、編集することができます。この領域をウィンドウと呼びます。

Windows システムにも「ウィンドウ」という概念があるのでややこしいですが、仕方がありません。

モード行と呼ばれる C の領域にはバッファの名前や状態などが表示されます。一番左の ----- はバッファの変更状態を示すもので、バッファの内容が変更されておりファイルに保存されていないとき、--**- になり、バッファの内容を変更できないとき --%%- になります。その少し右にある [utf8:crlf] という部分は、コロン(:)の左側が文字コード、右側が改行コードを示します。この例では、文字コードは UTF-8 で、改行コードは CR + LF です。

文字コードとしては、sjiseuc-jpwin-greek など他にも多数あります。改行コードは CR + LF(Windows 式)、 LF(Unix 式)、 CR(Macintosh 式) のいずれかです。

D の部分はエコー領域と呼ばれ、ユーザーにメッセージを表示するために、あるいは編集コマンドに関連してユーザーに文字を入力させるために使用されます。ミニバッファと呼ばれることもあります。

基本操作 (1) - ファイル

キー機能備考
C-n新規作成
C-o開くダイアローグボックスが開く
C-s上書き保存ファイル名がない時はダイアローグボックスが開く
F12名前を変えて保存ダイアローグボックスが開く

C-o あるいはメニューの [ファイル]-[開く] を使って Unicode (UTF-8) のファイルを開く際、エンコーディングを「自動判定」にしたままだとうまく開けないかもしれません。確実を期すならエンコーディング一覧から Unicode (UTF-8) を選んでから開いてください。
次の方法を使うと、もっと早く確実に Unicode (UTF-8) のファイル(例として C:¥home¥pdic¥sample.xml)を開くことができます。 2度目以降は、utf8 と入力するところで、上の矢印キーを押すと utf がエコー領域に出てきます。同様に、ファイル名を入力するところで上の矢印キーを何度か押すと、以前に入力したファイル名が出てきます。こういう便利な仕組みがあるため、面倒でもコントロールキーによるコマンドを覚えた方が楽です。
xyzzy による文字コードの自動判定が失敗した場合には、C-u C-x C-v コマンドを使うと便利です。C-u C-x C-f と同様の手順でファイルを開きなおします。

基本操作 (2) - 編集

準備作業(2)で私の .xyzzy をホームディレクトリに保存した場合、編集操作は Microsoft Word や「メモ帳」とあまり違いません。マウスで切り抜きや貼り付けをしたい人は、メニューの [表示]-[ツールバー]-[標準] を選んでください。

キー機能備考
矢印カーソル移動
S-矢印選択しながらカーソル移動
C-x選択範囲を切り抜き範囲が選択されていない時は、複合コマンドの1つ目。
C-c選択範囲をコピー範囲が選択されていない時は、複合コマンドの1つ目。
C-v貼り付け
C-zやり直し
C-yリドゥやり直しのやり直し
C-aすべてを選択
Home行の先頭にカーソル移動
End行の末尾にカーソル移動
S-Home行の先頭まで選択
S-End行の末尾まで選択
PageUp前ページへ移動
PageDown次ページへ移動

基本操作 (3) - 検索・置換

キー機能備考
C-f検索ダイアローグボックスが開く
C-r置換ダイアローグボックスが開く
F3下に向かって次を検索
S-F3上に向かって次を検索

基本操作 (4) - その他

キー機能備考
C-x &外部プログラム実行Perl スクリプトの実行はこれで行う
C-gコマンドの中断誤操作により開始したコマンドを中断する

おそらく初心者にとって最も大事なコマンドが C-g です。Windows ではキャンセルをするのに ESC を押すのが普通ですが、xyzzy ではこんなキーを使うのです。

はじめての Perl プログラミング

おさらい

Step 2 までに出てきたツール群を次表にまとめます。

名称引数 1引数 2機能
pdic2txtfoo.dicfoo.txtPDIC辞書ファイル ⇒ テキストファイル(Shift JIS)
txt2pdicfoo.txtfoo.dicテキストファイル(Shift JIS) ⇒ PDIC辞書ファイル
pdic_utf8foo.dicfoo.txtPDIC辞書ファイル ⇒ テキストファイル(Unicode/UTF-8)
utf8_pdicfoo.txtfoo.dicテキストファイル(Unicode/UTF-8) ⇒ PDIC辞書ファイル
pdic_xmlfoo.dicfoo.xmlPDIC辞書ファイル ⇒ XML 文書
xml_pdicfoo.xmlfoo.dicXML 文書 ⇒ PDIC辞書ファイル

PDIC Toolkit Ver. 1.13 より、引数として指定するファイルの拡張子を省略できるようになりました。また、引数 2 のファイルの本体が引数 1 のそれと同じである場合は、引数 2 自体を省略できます。つまり、次の 2 つのコマンドの意味は同じです。

pdic_xml greek.dic greek.xml[ENTER]
pdic_xml greek[ENTER]

フィルター

PDIC Toolkit Ver. 1.13 のもう1つの、より重要な進歩は、フィルターを指定できるようになったことです。フィルターの例として Toolkit に verb.pl が付属しています。これは、用例欄(希日辞典プロジェクトでは、ここに品詞の略称を書くことになっています)が“ρ.”で始まる項目(つまり、動詞)だけを抜き出すためのものです。

上の表にある6つのコマンドのうち、pdic2txttxt2pdic はフィルター機能に対応していません。

フィルターを指定するには次のようにコマンドを入力します。

pdic_xml --filter verb.pl greek.dic greek.xml[ENTER]
もちろん、これは次のように簡潔に書いても同じことです。
pdic_xml --filter verb.pl greek[ENTER]

xyzzy を起動し、C-u C-x C-fverb.pl を開くと、次のようなスクリプトが表示されます。

package MY::Filter; use utf8; sub filter { my $entry = shift; if ($entry->{example} =~ /^ρ\./) { return 1; } else { return 0; } } 1;
3行目の "ρ" の次の文字 "\"(バックスラッシュ)は、日本語キーボード上にはありませんが "¥" のキーで入力できます。

verb.pl をフィルタとして pdic_xml を実行するには C-x & と入力し、エコー領域に表示される & の右に

pdic_xml --filter verb.pl greek verb[ENTER]

と入力します。

すると、ウィンドウが上下2つに分かれて、上のウィンドウにスクリプトの実行結果が表示されます。

外部コマンドの実行結果は *Command Output* という名前のバッファに一時的に保持されます。C-x C-n でこのバッファに(仮の)ファイル名を付ければ、複数の実行結果を別々のバッファに保持して比較することができます。

要点はココ

さて、verb.pl の要点は次の部分です。

if ($entry->{example} =~ /^ρ\./) { return 1; } else { return 0; }

さらに煎じ詰めれば、次の部分に「動詞だけを抜き出す」という verb.pl の機能のエッセンスが詰まっています。

$entry->{example} =~ /^ρ\./

変数 $entry->{example} には、今検討している項目の用例欄(example)の内容が格納されています。/^ρ\./ は次項で説明する「正規表現」です。演算子 =~ は、その左側の変数に対して正規表現によるマッチングが行われることを示します。

この条件が満たされた場合には、if 節の中括弧ペアの内側、すなわち return 1; が実行されます。この文はサブルーチン filter を呼んだプログラム(pdic_xml など)に 1 という値を返します。条件が満たされなかった場合には、else 節の中括弧ペアの内側、すなわち return 0; が実行されます。つまり、プログラム本体側は 0 という値を受け取るわけです。

pdic_xml などのプログラムは、サブルーチン filter1 を返した場合にのみ項目をファイルに出力します。フィルター機能はこういう仕組みでできているのです。

$entry->{example} の部分は、次のリストのうちの1つで置き換えることができます。

表現フィールド
$entry->{headword}見出し語
$entry->{pronunciation}発音
$entry->{definition}日本語訳
$entry->{example}用例
$entry->{level}レベル
$entry->{marked}暗記必須フラグ
$entry->{revised}修正フラグ

verb.pl についてもっと詳しく知りたい方は Appendix A をご覧下さい。

フィルターを書く

正規表現とは

正規表現とは、文字列のパターンを特殊記号(メタキャラクター)と文字の組み合わせで表現したものです。例えば、「"c" で始まり "t" で終わる小文字のアルファベットの列」というパターンは次のように表現されます。

^c[a-z]+t$

この正規表現は、"cat"、"chat"、"cut"、"component" などの様々な英単語にマッチします。この表現の中では ^ [ - ] + $ の6文字がメタキャラクターです。これは他愛のない例に過ぎませんが、Perl の正規表現は極めて強力なので、思いつく限りの様々なパターンを記述することができます。

極めて強力すなわち極めて複雑、ということでもあります。Active Perl に付属するマニュアルの perlre の項(英語)は網羅的ですが、初心者が読みこなすのは難しいでしょう。とりあえずは、
Perl プログラミング講座 : 「8章 正規表現
に目を通すとよいでしょう。Perl(Ver. 5.005)マニュアルを日本語訳した「正規表現(perlre)」もありますが、日本語ならわかりやすいだろうと考えるのは早計です。

先ほどの verb.pl では、次の下線部分が正規表現です。

         $entry->{example} =~ /^ρ\./

まず最初のキャレット ^ は「対象となる文字列の先頭」にマッチするメタキャラクターです。次の ρ は普通の文字(ギリシャ文字のロー)です。バックスラッシュ \ は、次に続く文字(列)と組み合わさって様々な意味を持ちますが、ここでは次のドット . を普通の文字に戻す役割を果たしています。本来、ドット . は「改行文字を除く任意の文字1個」にマッチするメタキャラクターです。

要するに、^ρ\. という正規表現は「対象となる文字列の先頭に "ρ." がある場合」というパターンを示す、ということになります。

上の例のように、Perl では正規表現を2つのスラッシュ / で囲んで示します。

スラッシュ自体はメタキャラクターではないのですが、正規表現を囲む区切り文字(デリミタ)であるため、正規表現内にある場合はバックスラッシュを前に付けなくてはなりません。したがって、正規表現の中にスラッシュが多く含まれる場合は非常に読みづらくなります。例えば、http://www.perl.org/ で始まる文字列にマッチする正規表現は ^http://www\.perl\.org/ ですが、Perl スクリプトの中で2つのスラッシュで囲もうとすると、
/^http:\/\/www\.perl\.org\.\//
と書くことになり、目がチカチカしてきます。そこで、Perl では次のようにも書くことができるようになっています。
m#^http://www\.perl\.org/#
m で始まっている限り、英数字および空白文字以外の任意の記号をデリミタとして使用できます。ただし、括弧類 { } ( ) [ ] < > を使う場合は、
m{^http://www\.perl\.org/}
のように、必ず対にして使う必要があります。

正規表現の例

正規表現の体系的な説明を始める元気はないので、例を見ながら学んでいただくことにしましょう。

^c[a-z]+t$

[a-z]文字クラスの一例です。"a" から "z" までの任意の文字1個にマッチします。[aeiuo] のようにハイフンを使わずに文字を並べることもできます。あるいは [0-9a-f] のように2つの範囲を組み合わせることもできます。

Perl 5.6 から Unicode (UTF-8) をちゃんと扱えるようになったため、スクリプトと対象文字列の文字コードが UTF-8 であれば、[α-ω][あ-ん] のような書き方もできます。ただし άα より前にあるのに ύυ より後ろにあるなど、文字コードの順番というのはなかなか複雑です。任意のギリシャ文字を示す文字クラスは [Ά-ώ] です。また任意のひらがなは [あ-ん] ではなく [ぁ-ん] と表現します。

次の +量指定子の1つで、直前の文字あるいはサブパターン(後述)が1回以上繰り返されることを意味します。[a-z]+ で1個以上の連続する小文字のアルファベットにマッチします。よく似た量指定子に * があります。これは0回以上の繰り返しを示します。i[a-z]+t は "it" にマッチしませんが、i[a-z]*t はマッチします。

最後の $ は、文字列の末尾にマッチするメタキャラクターです。これがないと、"category" など "t" で終わらない文字列にもマッチしてしまいます。

(ου|ιε)μαι$

(A|B) という形の正規表現は "A" または "B" にマッチします。この例は ουμαι または ιεμαι で終わるというパターンの正規表現です。

【法律?】

メタキャラクター ? も量指定子の1つで、0回または1回の繰り返し(変な言い方ですが)を意味します。この例は 【法】 または 【法律】 にマッチします。

条件式

verb.plif で始まる行を次のように変更し、名前を変えて保存してください。

    if  ($entry->{level} == 3) {

このフィルターはレベルが 3 の項目だけを抜き出します。== は2つの数値が等しいときに真を返す比較演算子です。レベルが 2 以上の項目を抜き出すなら、条件式を $entry->{level} >= 2 に変えてください。

    if  ($entry->{definition} eq '') {

eq は 2 つの文字列が等しいときに真を返す比較演算子です。このフィルターは日本語訳が空の項目だけを抜き出します。逆に、日本語訳が空でない項目だけを抜き出すには、条件式を $entry->{definition} ne '' に変えてください。ne"not equal" の略で、2 つの文字列が等しくないときに真を返す比較演算子です。

    if  ($entry->{example} =~ /^ρ\./ and $leve->{level} >= 3) {

このフィルターは、用例が "ρ." で始まり、かつ、レベルが 3 以上の項目を抜き出します。and は 2 つの条件式が共に成り立つときに真を返す論理演算子です。

次は…

PDIC Toolkit Tutorial - Step 4 では PDIC Toolkit における XML の具体的な利用法を説明します。


黒田努 <tkrd@mail.com> (2002.02.27)