今どき(今頃?)のperlのopen事情

いわずと知れたdankogai氏のちょっと前の記事ですが。

はてブでも複数指摘があった通り、ベアワードのファイルハンドルの使用は、STDIN, STDOUT, STDERR, ARGVなど、あらかじめ用意されているものに限り、あとはopen my $fh, ...やopendir my $dh ...を使いましょう。

あと、openが失敗した場合に備えましょう。
before:

open IN, '< _lsres_';

after:

open my $fh, '<', '_lsres_' or die $!;

または

my $filename = '_lsres_';
open my $fh, '<',  $filename or die "filename : $!";<<


404 Blog Not Found:perl - 勝手に添削 - Perl入門#1@ITPro

うわー、こんな書き方できるのか。さすがにopenでファイルハンドルを生で使うのは鬱陶しかったのでずっとFileHandleモジュール使ってたけどこれは時代遅れなのね。

shellに依存しないようにするためには、以下のようにします。

open my $pipe, '-|' or exec 'ls', '-la', $sdir or die $!;

このあたりのことは、perldoc perlsecを参照のこと。


404 Blog Not Found:perl - 勝手に添削 - Perl入門#1@ITPro


これ見てふと思ったんだけど、

cat hogehoge.txt | sort | uniq 


みたいにパイプを連続するにはどうすればいいのやら?


調べてみたら、perldoc perlfuncのopenの項目あたりにヒントが。

If you open a pipe on the command '-', i.e., either '|-' or '-|' with 2-arguments (or 1-argument) form of open(), then there is an implicit fork done, and the return value of open is the pid of the child within the parent process, and 0 within the child process. (Use defined($pid) to determine whether the open was successful.)

…なるほど。暗黙的にforkされてんのか。


だとしたら…

#!/usr/bin/perl

use strict;
use warnings;

if (my $pid = open my $pipe, '-|') {
    while(<$pipe>) {
        print '[parent]: ' . $_;
    }
    close $pipe;
}
else {
    open my $pipec, '|-' or exec 'sort', '-nk1' or die $!;
    print $pipec "70  banana\n";
    print $pipec "200 melon\n";
    print $pipec "50  apple\n";
    print $pipec "120 orange\n";
    close $pipec;
    close $pipe;
    exit;
}

こんな感じで…

[parent]: 50  apple
[parent]: 70  banana
[parent]: 120 orange
[parent]: 200 melon

おー動いた!


しかし直感的じゃねーな・・他にいい書き方ないのかな?