NAME

perlfaq9 - ネットワーク


DESCRIPTION

このセクションでは、ネットワーク、インターネット、web に関する 質問を扱っています。

CGI スクリプトからの返答の正しい形は?

(Alan Flavell <flavell+www@a5.ph.gla.ac.uk> が答えます...)

The Common Gateway Interface (CGI) はプログラム("CGI スクリプト")と web サーバ (HTTPD) の間のソフトウェアインターフェースを定めています。 これは Perl 固有のものではないので、独自の FAQと独自のチュートリアル、 そして独自の usenet group である comp.infosystems.www.authoring.cgi が あります。

CGI 仕様は RFC に概要が述べられています: http://www.ietf.org/rfc/rfc3875

その他の関連する文書のリストは http://www.perl.org/CGI_MetaFAQ.html に あります。

これらの Perl FAQ はいくつかの CGI の問題についてとても抜粋して カバーしています。 しかし、これらの詳細に用心するために、Perl プログラマは CGI モジュールを 使うことを強く忠告されます。

(CGI 仕様に定義されている) CGI レスポンスヘッダと、(RFC2616 の HTTP 仕様で 定義されている) HTTP レスポンスヘッダの類似性は意図的なものですが、 時々混乱を引き起こします。

CGI 仕様は 2 種類のスクリプトを定義しています: "Parsed Header" スクリプトと、"Non Parsed Header" (NPH) スクリプト。 何をサポートしているかについてはサーバーのドキュメントをチェックして ください。 "Parsed Header" スクリプトは色々な側面においてより単純です。 CGI 仕様は CGI レスポンスとして一般的な改行表現のどれを使ってもよいことに なっています(そこから正確な HTTP レスポンスを作成するのはサーバの仕事です)。 従って "\n" をテキストモードで書くのは技術的に正しく、推奨されています。 NPH スクリプトではより微妙です: ここでは完全に正確な HTTP トランザクション レスポンスヘッダを出力しなければなりません; HTTP 仕様はレコードが復帰と 改行(つまりバイナリモードで ASCII コードの \015\012 が書かれる)で 終端されていることを要求します。

CGI.pm を使うことで、EBCDIC システムを含むすばらしいプラットフォーム 独立性が得られます。 CGI.pm は適切な改行表現を選択し($CGI::CRLF)、binmode を適切にセットします。

私の CGI スクリプトはコマンドラインでは動くのだけど、ブラウザ上では動きません (500 Server Error になります)

可能性はいくつかあります。 以下にある "Troubleshooting Perl CGI scripts" ガイドを読みましょう:

        http://www.perl.org/troubleshooting_CGI.html

その後、FAQ を読んで、あなたの問題が簡単に答られるものではないと わかったのなら、(HTTP や CGI プロトコルに関するものなら) comp.infosystems.www.authoring.cgi にポストすれば有用なリプライが 得られるでしょう。 Perl に関する質問のように見えていても、実は CGI に関するものだというものが comp.lang.perl.misc に投稿されることがありますが、回答はついていません。

便利な FAQ、関連するドキュメント、トラブルシューティングガイドは CGI Meta FAQ に挙げられています:

        http://www.perl.org/CGI_MetaFAQ.html

CGI プログラムから、もっとまともなエラーメッセージを得るには?

CGI::Carp モジュールを使いましょう。 このモジュールは warndie の置き換えを行い、さらに通常の Carp モジュールの carpcroakconfess といった関数をより饒舌で 安全なものに置き換えます。 その出力は、サーバーの通常のエラーログに送られます。

        use CGI::Carp;
        warn "This is a complaint";
        die "But this one is serious";

以下の CGI::Carp の使用例では、エラーをあなたの選択したファイルへ リダイレクトし、コンパイル時の警告も同様に補足するため BEGIN ブロックに 置いています:

        BEGIN {
                use CGI::Carp qw(carpout);
                open(LOG, ">>/var/local/cgi-logs/mycgi-log")
                        or die "Unable to append to mycgi-log: $!\n";
                carpout(*LOG);
        }

深刻なエラーをクライアントのブラウザに戻すように変更することもできます。 これはあなたがデバッグするには良いでしょうが、エンドユーザーを 混乱させてしまうかもしれません。

        use CGI::Carp qw(fatalsToBrowser);
        die "Bad error here";

あなたが HTTP ヘッダーを受け取るよりも前にエラーが起こったとしても、 モジュールはサーバーの 500 エラーを避けるためにそのエラーを取り扱おうと するでしょう。 通常の警告はサーバーのエラーログ(もしくはあなたが carpout で指定した場所)に アプリケーションの名前と日付を伴って送られます。

ある文字列から HTML を取り除くには?

(最速ではありませんが)最も正しい方法は、CPAN にある HTML::Parser を 使うというものです。 もう一つのまず正しい方法は、HTML::FormatText を使って HTML を 取り除くだけでなく、結果のプレーンテキストを簡単に整形することです。

多くの人が、s/<.*?>//g のような単純な(simple-minded)正規表現を 使ったアプローチを行おうとするのですが、これは多くの場合 失敗していまいます。 なぜなら、タグは行をまたがって継続する可能性があり、 クォートされたアングルブラケットを含む可能性があり、 HTML のコメントがあるかもしれないからです。 さらに、人々は &lt; のようなエンティティを変換することを忘れてしまうのです。

以下の例は「単純な」アプローチで、ほとんどのファイルに対しては うまくいきます:

        #!/usr/bin/perl -p0777
        s/<(?:[^>'"]*|(['"]).*?\1)*>//gs

もし、より完璧な解決策を求めているのなら、 http://www.cpan.org/authors/Tom_Christiansen/scripts/striphtml.gz にある 3-stage striphtml プログラムを参照してみてください。

以下に挙げたのは、あなたが自分でやろうとしたときに 考慮すべきであろうトリッキーな例です:

        <IMG SRC = "foo.gif" ALT = "A > B">
        <IMG SRC = "foo.gif"
         ALT = "A > B">
        <!-- <A comment> -->
        <script>if (a<b && a>c)</script>
        <# Just data #>
        <![INCLUDE CDATA [ >>>>>>>>>>>> ]]>

以下のテキストのように HTML のコメントが他のタグを含んでいた場合には、 せっかくの対応策もダメにしてしまうかもしれません:

        <!-- This section commented out.
                <B>You can't see me!</B>
        -->

URL の展開を行うには?

アンカー、イメージ、オブジェクト、フレーム、およびその他の URL を含む 多くのタグを扱える HTML::SimpleLinkExtor を使って、HTML からあらゆる 種類の URL を簡単に抽出できます。 もしもっと複雑なものが必要なら、自分自身で HTML::LinkExtorHTML::Parser のサブクラスを作れます。 例えば、あなたの用途に特に適用するなら、HTML::SimpleLinkExtor を 使うこともできます。

任意のテキスト文書から URL を抽出するためには、URI::Find が使えます。

もし入力が単純であることが分かっているなら、正規表現を使ったより不完全な 解法によって多くの処理時間を節約できます。 Tom Christiansen による一つの解法は、モジュールを使った手法よりも 100 倍 速いですが、最初の属性が HREF で、その他の属性がないアンカーの URL のみを 抽出します。

        #!/usr/bin/perl -n00
        # qxurl - tchrist@perl.com
        print "$2\n" while m{
                < \s*
                  A \s+ HREF \s* = \s* (["']) (.*?) \1
                \s* >
        }gsix;

ユーザーのマシンからファイルをダウンロードするには? 別のマシンにあるファイルをオープンするには?

この場合、ダウンロードというのは HTML フォームのファイルアップロード機能を 使うということを意味します。 Web サーファーに、Web サーバーに送るファイルを指定できるようにします。 あなたにとってダウンロードに見えるものは、ユーザーにとってはアップロードに 見えます。 何と呼ぶかには関わらず、multipart/form-data エンコーディングとして知られているものを使うことができるでしょう。 CGI.pm モジュール(標準ライブラリになっています)はこれを start_multipart_form() という starform() メソッドとは異なるメソッドでサポートしています。

コードのサンプルと詳細については、CGI.pm の文書のファイルアップロードの 章を参照してください。

Perl で HTML のポップアップメニューを作るには?

(brian d foy によって寄贈されました)

CGI.pm モジュール(標準配布です)には HTML フォームウィジェットを作るための 関数があります。 更なる例については CGI.pm の文書を参照してください。

        use CGI qw/:standard/;
        print header,
                start_html('Favorite Animals'),
                start_form,
                        "What's your favorite animal? ",
                popup_menu(
                        -name   => 'animal',
                        -values => [ qw( Llama Alpaca Camel Ram ) ]
                        ),
                submit,
                end_form,
                end_html;

HTML ファイルをフェッチするには?

(brian d foy によって寄贈されました)

libwww-perl ディストリビューションを使ってください。 LWP::Simple はウェブ上のリソースをフェッチして、その内容を文字列として 返します:

        use LWP::Simple qw(get);
        my $html = get( "http://www.example.com/index.html"; );

リソースを直接ファイルに保存することもできます:

        use LWP::Simple qw(getstore);
        getstore( "http://www.example.com/index.html";, "foo.html" );

もっと複雑なことをする必要がある場合は、仕事を行うための独自の ユーザーエージェント(例えばブラウザ)を作るために LWP::UserAgent モジュールを使えます。 対話的なウェブブラウザをシミュレートしたい場合は、 WWW::Mechanize モジュールが使えます。

HTML フォームの処理を自動化するには?

もし、複数のページとフォームや web サイトを移動するような、複雑なことを しようとしているなら、WWW::Mechanize が使えます。 全ての詳細についてはこれのドキュメントを参照してください。

GET メソッドを使って値を処理しているのであれば、URL を作って、 さらに query_form メソッドを使ってフォームをエンコードします:

        use LWP::Simple;
        use URI::URL;
        my $url = url('http://www.perl.com/cgi-bin/cpan_mod');
        $url->query_form(module => 'DB_File', readme => 1);
        $content = get($url);

POST メソッドを使っているのであれば、自分用のエージェントを作成して コンテンツを適切にエンコードしてやります。

        use HTTP::Request::Common qw(POST);
        use LWP::UserAgent;
        $ua = LWP::UserAgent->new();
        my $req = POST 'http://www.perl.com/cgi-bin/cpan_mod',
                                   [ module => 'DB_File', readme => 1 ];
        $content = $ua->request($req)->as_string;

web上で %-encodings をデコードしたり生成したりするには?

(brian d foy によって寄贈されました)

これらの % 符号化は RFC 2396 の 2 章に記述されている、 URI として予約されている文字を扱います。 この符号化は予約文字を、その文字の番号の 16 進表現に US-ASCII テーブルを使って置き換えます。 例えば、コロン (:) は %3A になります。

CGI スクリプトでは、CGI.pm を使っているなら URL のデコードについて 気にする必要はありません。 エンコードにしてもデコードにしても、URI を自分で処理する必要はないはずです。

もし文字列を自分でエンコードする必要があるなら、 決してすでに構成された URI をエンコードするべきではないことを 忘れないでください。 要素を別々にエスケープして、それから全てを合わせます。 文字列をエンコードするには、URI::Escape モジュールが使えます。 uri_escape 関数はエスケープされた文字列を返します:

        my $original = "Colon : Hash # Percent %";
        my $escaped = uri_escape( $original )
        print "$string\n"; # 'Colon%20%3A%20Hash%20%23%20Percent%20%25%20'

文字列をデコードするには、uri_unescape 関数を使います:

        my $unescaped = uri_unescape( $escaped );
        print $unescaped; # back to original

もしこれを自分でするなら、単に予約文字をエンコードされた物に置き換えます。 全体を一度に変換するなら、以下のようにします:

        # encode
        $string =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%0x", ord $1 /eg;
        #decode
        $string =~ s/%([A-Fa-f\d]{2})/chr hex $1/eg;

別のページにリダイレクトするには?

(たとえ同じサーバでも)宛て先の完全な URL を指定してください。 これは Parsed Headers スクリプトとして CGI 仕様に定義された二つの異なった CGI "Location:" レスポンスのうちの一つです。 その他の種類 (絶対 URL パス) は HTTP リダイレクトなしにサーバによって 内部的に解決されます。 CGI 仕様ではどちらの場合でも相対 URL は認められていません。

CGI.pm を使うことを強くお勧めします。 この例では完全な URL へのリダイレクトを行います。 このリダイレクトは web ブラウザによって扱われます。

        use CGI qw/:standard/;
        my $url = 'http://www.cpan.org/';
        print redirect($url);

この例では絶対 URL パスへのリダイレクトを行います。 このリダイレクトはローカルの web サーバによって行われます。

        my $url = '/CPAN/index.html';
        print redirect($url);

しかし、直接コーディングするなら、完全な URL か絶対 URLpath を使って、 以下のようになります(最後の "\n" は明確化するために分けて表示しています)。

        print "Location: $url\n";   # CGI response header
        print "\n";                 # end of headers

私の web ぺージでパスワードを入力するには?

利用する Web サーバーで認証を有効にするには、Web サーバーを設定することが 必要です。 web サーバの種類によって設定は異なります -- apache は iPlanet とは異なり、 また IIS とも異なります。 特定のサーバーに関する詳細については、そのサーバーのドキュメントを チェックしてください。

Perl を使って .htpasswd や .htgroup といったファイルを編集するには?

HTTPD::UserAdmin モジュールと HTTPD::GroupAdmin モジュールは、 ファイルがどのように格納されているかに関係なくこれらのファイルに対する 首尾一貫したオブジェクト指向インターフェースを提供します。 データベースはテキスト、dbm、Berkeley DB、あるいは DBI 互換ドライバのある どんなデータベースでもかまいません。 HTTPD::UserAdmin は "Basic" および "Digest" 認証スキームで 使われるファイルをサポートします。 以下に例を挙げます:

        use HTTPD::UserAdmin ();
        HTTPD::UserAdmin
          ->new(DB => "/foo/.htpasswd")
          ->add($username => $password);

私の CGI スクリプトに悪影響をもたらすようなものを、ユーザーがフォームに入力できないようにするには?

CGI Meta FAQ に挙げられているセキュリティに関する参考資料を参照してください。

        http://www.perl.org/CGI_MetaFAQ.html

メールのヘッダーを解析するには?

拙速な解決策なら、split in perlfunc から派生した 以下のやり方を試してみてください。

        $/ = '';
        $header = <MSG>;
        $header =~ s/\n\s+/ /g;  # merge continuation lines
        %head = ( UNIX_FROM_LINE, split /^([-\w]+):\s*/m, $header );

このやり方は、たとえば受信した行すべてを保守しようとするときには うまくありません。 より完璧なアプローチはCPANにあるMail::Header モジュールを 使うというものです(このモジュールは MailTools パッケージの一部です)。

CGI フォームをデコードするには?

(brian d foy によって寄贈されました)

Perl に同梱されている CGI.pm モジュールを使いましょう。 これは早く、簡単で、物事が正しく行われることを確実にするための ちょっとした作業を行います。 GET, POST, HEAD リクエスト、マルチパートフォーム、複数値フィールド、 クエリ文字列とメッセージボディの組み合わせ、およびその他の、 あなたが考えようとも思わないような多くの事柄を扱えます。

これ以上簡単にはなりません: CGI モジュールは入力を自動的にパースして、 それぞれの値を param() 関数を通して利用可能にします。

        use CGI qw(:standard);
        my $total = param( 'price' ) + param( 'shipping' );
        my @items = param( 'item' ); # multiple values, same field name

オブジェクト指向な手法が使いたいなら、CGI.pm はそのようにもできます。

        use CGI;
        my $cgi = CGI->new();
        my $total = $cgi->param( 'price' ) + $cgi->param( 'shipping' );
        my @items = $cgi->param( 'item' );

同じことをする軽量版の CGI::Minimal も試したいかもしれません。 CPAN にあるその他の CGI::* モジュールもあなたのためによく働くでしょう。

多くの人々が自分用のデコーダを書こうとします (あるいは他のプログラムから コピーしようとします); そしてこの作業の多くの「コツ」の一つに出くわすことに なります。 CGI.pm を使うことはより簡単で、面倒事も少なくなります。

メールアドレスが正しいかチェックするには?

(一部は Aaron Sherman によって寄贈されました)

これは見た目ほど単純な質問ではありません。 これは二つの部分からなります:

a) メールアドレスが正しい形式かを検証するには?

b) メールアドレスが正当な受信者を対象としているかを検証するには?

そのアドレスにメールを送ってそれが届いたかどうかを確認しなければ 完全にパート b に答えられませんが、Email::ValidRFC::RFC822::Address のモジュールは、リアルタイムでできる限りの ことに対してパート a とパート b の両方を行います。

もしあなたが単純な正規表現でアドレスがメールヘッダ標準に従っているかを 見ることでパート a をチェックしたいなら、問題を抱えることになります; なぜなら、RFC-2822 (最新のメールヘッダ標準) に準拠してないけれども 配達可能なアドレスが存在し、標準に準拠しているけれども配達不能なアドレスも 存在するからです。 しかし以下のコードは、コメント、折り畳みの空白、あるいはその他の時代遅れに なっていたり本質的でない要素を含んでいない、有効な RFC-2822 アドレスに マッチングします。 これは 単に アドレス自身にマッチングします:

        my $atom       = qr{[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+};
        my $dot_atom   = qr{$atom(?:\.$atom)*};
        my $quoted     = qr{"(?:\\[^\r\n]|[^\\"])*"};
        my $local      = qr{(?:$dot_atom|$quoted)};
        my $quotedpair = qr{\\[\x00-\x09\x0B-\x0c\x0e-\x7e]};
        my $domain_lit = qr{\[(?:$quotedpair|[\x21-\x5a\x5e-\x7e])*\]};
        my $domain     = qr{(?:$dot_atom|$domain_lit)};
        my $addr_spec  = qr{$local\@$domain};

もしアドレスが RFC 2822 仕様に準拠しているかどうかを見たいなら、単に /^${addr_spec}$/ とマッチングさせてください。 しかし、このような正しい形式のアドレスが実際に特定の個人に届く 正しい方法なのか、あるいはその個人に関連付けられたメールボックスに 届くのかさえも明確にすることは不可能なので、これをどう使うかについては とても慎重になる必要があります。

私たちができる最善のアドバイスは、個人のメールアドレスをチェックするのに パスワードを変更するときと同じようにユーザーにアドレスを 二回入力させるというものです。 これによって通常は打ち間違いを防ぐことができます。 二回の入力がマッチしたなら、個人的な内容のメッセージをメールとして そのアドレスへ送ります。 もしメッセージが返ってきて、それがあなたの指示に従っているなら、 それが実際のものであると十分に仮定できます。

より偽造のやりにくい別のやり方に、チェックに対象者に対して PIN (Personal ID Number) を与えるというものがあります。 後の処理のためにアドレスと PIN (ランダムであることが望ましい)を 記録しておくのです。 あなたがメールを送るときに、宛て先人に対して彼らの出すリプライに PIN を含めるように依頼するのです。 しかしそれがそのまま返ってきたり、あるいは返ってきたメッセージが "vacation" スクリプトを通じてのものであっても、そのまま PIN が 含まれてしまいます。 ですから、最善なやり方はメールを送るときに返事には文字を逆順にするとか、 各桁に対して足し算や引き算を行うなどして PIN を変形したものを含めて返すように依頼するという方法です。

MIME/BASE64 文字列のデコードを行うには?

MIME-Base64 パッケージ(CPAN で入手可能です)はこの問題と、 MIME/QP エンコーディングを取り扱います。 BASE64 のデコードは以下のように単純です:

        use MIME::Base64;
        $decoded = decode_base64($encoded);

MIME-Tools パッケージ (CPAN にあります) は BASE64 エンコードされた 添付ファイルと本文をメールのメッセージから直接抽出できます。

もしデコードしたい文字列が短い(84 文字以下)の場合、より直接的なやり方は、 ちょっとした変換をした後で unpack() 関数の "u" フォーマットを 使うというものです:

        tr#A-Za-z0-9+/##cd;                   # remove non-base64 chars
        tr#A-Za-z0-9+/# -_#;                  # convert to uuencoded format
        $len = pack("c", 32 + 0.75*length);   # compute length byte
        print unpack("u", $len . $_);         # uudecode and print

ユーザーのメールアドレスを返すには?

getpwuid をサポートしているシステムであれば、$< という変数と Sys::Hostname モジュール(標準の perl 配布キットの一部です)を使って 以下のようなことが試せるでしょう。

        use Sys::Hostname;
        $address = sprintf('%s@%s', scalar getpwuid($<), hostname);

会社のメールアドレスに関するポリシーが、これが生成するアドレスは その会社のメールシステムが受け付けないものである可能性があります。 ですから、ユーザーに、そのユーザーのメールアドレスを尋ねるべきでしょう。 それに加え、Perl が動作する全てのシステムで この情報が(UNIX と同じように)得られるわけではありません。

CPAN にある Mail::Util モジュール (MailTools パッケージの一部です)は メールアドレスがそのユーザーのものであるかどうかを確かめようとする mailaddress() という関数を提供しています。 これは上で例示したやり方よりも賢く、モジュールがインストールされたときの 情報を使いますが、それでも正しくない可能性があります。 くり返しますが、最善の方法はユーザーに尋ねること、というのがほとんどです。

メールを送るには?

sendmail プログラムを直接使います:

        open(SENDMAIL, "|/usr/lib/sendmail -oi -t -odq")
                or die "Can't fork for sendmail: $!\n";
        print SENDMAIL <<"EOF";
        From: User Originating Mail <me\@host>
        To: Final Destination <you\@otherhost>
        Subject: A relevant subject line
        Body of the message goes here after the blank line
        in as many lines as you like.
        EOF
        close(SENDMAIL)     or warn "sendmail didn't close nicely";

-oi オプションは sendmail がドットだけの行を“メッセージの終わり”と みなさないようにするためのオプションです。 -tオプションはメッセージを誰に送るかを決めるかのために ヘッダーを使うことを指示し、-odq オプションメッセージを キューに入れることを指示します。 最後のオプションの意味は、あなたのメッセージがすぐには配送されないことを 意味します。 ですから、すぐに配送させたいのであればこのオプションを取り除いてください。

あるいは、直接 mail (mailx と呼ばれることもあります)を呼びだしたり、 単純に 25 番ポートを使ってリモートの SMTP デーモン(多分 sendmail でしょう) との間で詳細な通信を行うといったあまり便利でない方法もあります。

あるいは CPAN にあるモジュール Mail::Mailer が使えるかもしれません:

        use Mail::Mailer;
        $mailer = Mail::Mailer->new();
        $mailer->open({ From    => $from_address,
                                        To      => $to_address,
                                        Subject => $subject,
                                  })
                or die "Can't open: $!\n";
        print $mailer $body;
        $mailer->close();

Mail::Internet モジュールは Mail::Mailer より UNIX 的ではない Net::SMTP を使っていますが、信頼性も低いです。 生の SMTP コマンドを無視します。 sendmail のような mail transport agent を使う理由はたくさんあります。 その中にはキューイングも含まれますし、MX レコードやセキュリティと いったものが含まれます。

メールメッセージに添付するためにどうやって MIME を使えばいいですか?

この回答は MIME::Lite のドキュメントから直接持ってきたものです。 マルチパートメッセージ(つまり 添付つきのメッセージ) を作ります。

        use MIME::Lite;
        ### Create a new multipart message:
        $msg = MIME::Lite->new(
                                 From    =>'me@myhost.com',
                                 To      =>'you@yourhost.com',
                                 Cc      =>'some@other.com, some@more.com',
                                 Subject =>'A message with 2 parts...',
                                 Type    =>'multipart/mixed'
                                 );
        ### Add parts (each "attach" has same arguments as "new"):
        $msg->attach(Type     =>'TEXT',
                                 Data     =>"Here's the GIF file you wanted"
                                 );
        $msg->attach(Type     =>'image/gif',
                                 Path     =>'aaa000123.gif',
                                 Filename =>'logo.gif'
                                 );
        $text = $msg->as_string;

MIME::Lite はまたこれらのものを送るためのメソッドを含みます。

        $msg->send;

これはデフォルトでは sendmail を使いますが、 Net::SMTP 経由で SMTP を使うようにカスタマイズできます。

メールを読み出すには?

CPAN にある Mail::Folder モジュール(MailFolder パッケージの一部です)や Mail::Internet モジュール(これも MailTools パッケージの一部です)が 使えますが、モジュールを使うのはやりすぎかもしれません。 以下にメールをソートする方法を示します。

        #!/usr/bin/perl
        my(@msgs, @sub);
        my $msgno = -1;
        $/ = '';                    # paragraph reads
        while (<>) {
                if (/^From /m) {
                        /^Subject:\s*(?:Re:\s*)*(.*)/mi;
                        $sub[++$msgno] = lc($1) || '';
                }
                $msgs[$msgno] .= $_;
        }
        for my $i (sort { $sub[$a] cmp $sub[$b] || $a <=> $b } (0 .. $#msgs)) {
                print $msgs[$i];
        }

あるいはもっと簡潔に:

        #!/usr/bin/perl -n00
        # bysub2 - awkish sort-by-subject
        BEGIN { $msgno = -1 }
        $sub[++$msgno] = (/^Subject:\s*(?:Re:\s*)*(.*)/mi)[0] if /^From/m;
        $msg[$msgno] .= $_;
        END { print @msg[ sort { $sub[$a] cmp $sub[$b] || $a <=> $b } (0 .. $#msg) ] }

How do I find out my hostname, domainname, or IP address? gethostbyname, Socket, Net::Domain, Sys::Hostname>

(brian d foy によって寄贈されました)

perl5.7.3 から標準配布されている Net::Domain モジュールを使うと、 完全修飾ドメイン名 (FQDN)、ホスト名、ドメイン名が得られます。

        use Net::Domain qw(hostname hostfqdn hostdomain);
        my $host = hostfqdn();

perl5.6 から標準配布されている Sys::Hostname モジュールでも ホスト名を得られます。

        use Sys::Hostname;
        $host = hostname();

IP アドレスを得るには、名前から数値に変換するために gethostbyname 組み込み関数が使えます。 数値を、ほとんどの人が想定しているピリオド付きの形 (a.b.c.d) に変換するには、 標準配布されている Socket モジュールの inet_ntoa 関数を使います。

        use Socket;
        my $address = inet_ntoa(
                scalar gethostbyname( $host || 'localhost' )
                );

ニュースの記事やアクティブなニュースグループを取得するには?

Net::NNTP モジュールか News::NNTPClient モジュールのいずれかを使います。 これらは両方ともCPANから入手可能です。 これらは以下のように簡単にニュースグループのリストを取得するような 作業ができます。

        perl -MNews::NNTPClient
          -e 'print News::NNTPClient->new->list("newsgroups")'

FTP ファイルをダウンロード/アップロードするには?

LWP::Simple (CPAN で入手可能)はダウンロードができますが アップロードはできません。 Net::FTP(これも CPAN で入手可能)はこれよりも複雑ですが、 ダウンロードとアップロードの両方ができます。

Perl で RPC を行うには?

(brian d foy によって寄贈されました)

CPAN ( http://search.cpan.org/search?query=RPC&mode=all ) で見付かる RFC モジュールの一つを使いましょう。


REVISION

Revision: $Revision$

Date: $Date$

See perlfaq for source control details and availability.


AUTHOR AND COPYRIGHT

Copyright (c) 1997-2009 Tom Christiansen, Nathan Torkington, and other authors as noted. All rights reserved.

This documentation is free; you can redistribute it and/or modify it under the same terms as Perl itself.

Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required.