blog20100901

2013/08/20 - プログラミング言語 Perl にまつわる etc. - Perl monger
参考 : perldoc, perldoc.jp, search.cpan.org, perldoc.perl.org ...
「 初めての Perl 第 6 版 」(オライリー・ジャパン発行 ISBN978-4-87311-567-2) 」
「 続・初めての Perl 改訂版 」(オライリー・ジャパン発行 ISBN4-87311-305-9) 」
「 Effective Perl 第 2 版 」(翔泳社発行 ISBN978-4-7981-3981-4) 」 ... etc,.

Perl Perl_5

Perl 外部のコードを実行する eval, do, require, use lib (d000)

Perl 外部のコードを実行する eval, do, require, use lib (d000)

目次 - Perl Index



Theme



Perl について、復習を兼ねて断片的な情報を掲載して行く連載その d000 回。

Perl で、外部のファイルに記述したプログラムコードを読み込んで実行する基本的な方法「 eval 」, 「 do 」, 「 require 」, 「 use lib 」を確認する。



外部ファイルからコードを読み込む



プログラミングにある程度慣れてくると、全体の処理内容は異なるけれど、部分的には以前書いたコードを流用したい場面が増えて来るかもしれません。

そうした場合のために、(0x8e) で確認したように Perl では「 モジュール 」という特定の規格にそってコーディングされた拡張機能を利用出来るようにしてあります。

「 モジュール 」は、一般的によく利用される処理 ( 特定の分野に特化したディープな処理もあります ) をまとめたプログラムコードの集まりなので、「 モジュール 」を使えば、同じような処理をいつでもどこでも流用することが出来ます。

Perl の「 コアモジュール 」( 標準モジュール ) として「 perl 」と共に配布されているモジュールは、プラグマ「 use 」を利用して呼び出す以外に、特別な何かをすることなく利用出来ます。

「 コアモジュール 」一覧は付属のドキュメント「 perlmodlib 」の 「 Standard Modules 」で確認出来ます。


$ perldoc perlmodlib



Web であれば、perlmodlib - perldoc.perl.org で同じもの ( Perl の version に注意します ) が確認出来ますし、モジュール「 Module::CoreList 」が利用可能なら、これに付属するツール「 corelist 」を利用してシェル上から確認することも出来ます。

例えば、Perl v5.14 のコアモジュールを確認したいのであれば次のようにします。


$ corelist -v 5.014
The following modules were in perl 5.014 CORE
AnyDBM_File 1.00
App::Cpan 1.5701
App::Prove 3.23
App::Prove::State 3.23
:
.



コアモジュール以外では、「 CPAN 」( Comprehensive Perl Archive Network ) と呼ばれる総合ネットワークアーカイブから好みのモジュールをダウンロードしてインストールすることも可能です。

もちろん規格に従ってコードディングすれば自前のモジュールを作成し利用することも出来ます。

モジュールはつまり、「 外部のファイルに記述されたプログラム 」を自分のファイルに読み込んで利用する仕組みであるわけですが、単に外部ファイルのプログラムを利用したいだけなら「 モジュール 」という体裁を整えなくても利用出来る機能が用意されています。

今回は、そうした外部プログラムをやや原始的に利用する方法を確認します。


文字列「 eval 」で読み込む



まずはじめに、文字列「 eval 」を利用する方法を確認します。

(0x271) で確認した通り、文字列「 eval 」は与えられた引数をあたかも Perl プログラムのように解釈して実行することが出来ます。

文字列「 eval 」は、意図しないコードが実行される恐れがあることが一般的に理解されていますが、十分に注意することで有用に利用することも出来ます。

今回の目的である外部ファイルのプログラムを実行するには、例えば次のようなプログラムコードを利用します。

ここでは次のプログラムをファイル名「 read.pl 」として保存します。これは外部ファイルを *読み込んで* 実行する側のプログラムです。*読み込まれる* 外部ファイルのファイル名は「 print.pl 」としました。


#!/usr/bin/perl

use strict;
use warnings;

# ファイル read.pl のコード

# read.pl の出力
print "Printed this with read.pl\n";

{
# 外部ファイルを open
open my $fh, '<', 'print.pl' or die "print.pl: $!";

# ファイルの内容を一気に読み込む吸い込みモードを設定
local $/;

# ファイルを読み込み
my $more_code = <$fh>;
close $fh;

# 文字列 eval で実行
eval $more_code;
die $@ if $@;
}



16 行目の特殊な組み込み変数「 $/ 」は、「 入力レコードセパレータ 」( The input record separator ) が設定されている変数です。

通常は「 改行文字 」がセパレータとして設定されているので、入力データで改行文字が現れるたびに入力がセパレートされますが、「 local $/ 」で中身を undef としておくことで、入力データをセパレートせずに一気に読み込むことが出来るようになります。

「 $/ = undef 」 や「 undef $/ 」 としても同様の効果がありますが、「 { } 」でスコープブロックを作り「 local 」でスコープを限定しておけば、他の部分への意図しない影響を防止することが出来ます。

組み込み変数「 $/ 」の詳細は $/ -perldoc.jp および perlvar - perldoc.jp で確認します。

外部ファイル「 print.pl 」のプログラムコードは、次の通りただの print 文です。


# print.pl のコード

# print.pl の出力
print "Then printed this with print.pl\n";



この状態でファイル「 read.pl 」を実行すると、次の結果が得られます。


$ perl read.pl
Printed this with read.pl
Then printed this with print.pl



外部ファイル「 print.pl 」から読み込んだ print 文が問題なく実行されていることが分かります。

ここでは、文字列「 eval 」によって読み込んだ文字列「 $more_code 」を Perl プログラムとして実行しているだけなので、外部ファイル「 print.pl 」には「 #! 」のシェバン行すら記述する必要はありません。

(0x25b) で確認したバッククォート演算子「 `` 」を利用すれば、読み込み側の「 read.pl 」をより簡潔にすることも出来ます。


#!/usr/bin/perl

use strict;
use warnings;

print "Printed this with read.pl\n";

# バッククォート演算子で cat を実行
eval `cat print.pl`;
die $@ if $@;



上記コードでは、システムコマンド「 cat 」の出力を Perl の「 eval 」で Perl プログラムコードとして解釈しています。


「 do 」で読み込む



(0x14) で確認した通り、「 do 」は文字列「 eval 」とだいたい同じです。


do 'outside.pl';

# is largely like

eval `cat outside.pl`;



ですから、読み込み側のファイル「 read.pl 」は次のように「 do 」で書き替えることが出来ます。


#!/usr/bin/perl

use strict;
use warnings;

print "Printed this with read.pl\n";

do 'print.pl';
die $@ if $@;



上記プログラムコードを実行してもやはり次の結果を得られます。


$ perl read.pl
Printed this with read.pl
Then printed this with print.pl



「 do 」では外部ファイルの入れ子の中のレキシカル変数を読めないが「 eval 」では読める、「 do 」はカレントディレクトリにファイルがなければ「 @INC 」を検索する等、「 eval 」と異なる部分があります。詳細は関連するドキュメント perlfunc - perldoc.jp 等を参照します。


「 require 」で読み込む



「 require 」でも同様に外部ファイルのプログラムを利用することが出来ます。


#!/usr/bin/perl

use strict;
use warnings;

print "Printed this with read.pl\n";

# require で外部ファイルを読み込み
require 'print.pl';



上記プログラムコードの実行結果は前項までと同じになります。

「 require 」は、読み込んだファイルに構文エラーが含まれていればプログラムを異常終了させるので、手動による「 $@ 」のチェックは不要になります。

それから、読み込んだファイルの式は必ず 真 を返さなければならないので、場合によっては読み込まれるファイル ( ここでは print.pl ) の最後の行を「 1; 」 とする必要があります。

また、「 require 」の引数に裸の単語 ( bareword ) を指定すると、カレントと「 @INC 」のディレクトリからサフィックスが「 .pm 」のファイルを探して読み込みます。

ですから、読み込まれるファイル「 print.pl 」を「 prints.pm 」( s/print/prints/, s/pl/pm/ ) に変更しておけば、「 require 」を次のように書き換えることも出来ます。


# カレントディレクトリの prints.pm を読み込んで実行
require prints;



「 require 」の詳細は require - perldoc.jp 等で確認出来ます。


「 use lib 」と「 require 」で読み込む



読み込みたいファイルが、カレントディレクトリにも「 @INC 」にもない場合であっても、モジュール「 lib 」で読み込み先のディレクトリを指定することで、目的のファイルを読み込んで利用することが出来ます。

例えば、読み込みたいファイル「 prints.pl 」のシステムパスが「 /home/your/dir/lib/ 」配下に設置されている場合、「 use lib 」で次のように設定すれば「 require 」で「 prints.pl 」を読み込むことが出来ます。


use lib '/home/your/dir/lib/';

# /home/your/dir/lib/prints.pl を読み込んで実行
require 'prints.pl';



ファイル名のサフィックスを「 .pm 」にしておけば裸の単語 ( bareword ) で指定出来るのは前項で確認しました。


# /home/your/dir/lib/prints.pm を読み込んで実行
require prints;




Next



次回は、外部ファイルのサブルーチンを必要に応じて利用する方法を確認します。


参考情報は書籍「 続・初めての Perl 改訂版 」, 「 Effective Perl 第 2 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。

目次 - Perl Index





























同じカテゴリー(Perl)の記事
 Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228) (2023-10-11 23:49)
 Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227) (2023-05-26 15:41)
 Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226) (2023-05-19 17:05)
 Perl mp2 翻訳 テンプレートシステムの選択 (d225) (2022-08-15 22:23)
 Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224) (2022-06-15 20:43)
 Perl mp2 翻訳 チュートリアル (d223) (2022-06-15 20:42)
上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

Llama
リャマ
TI-DA
てぃーだブログ
プロフィール
セラ (perlackline)
セラ (perlackline)
QRコード
QRCODE
オーナーへメッセージ

PAGE TOP ▲