Strings of Life

PHP/Phalcon/MySQL/JavaScript/RegExp/Ruby/Perl/ActionScript

タグ:Perl

グロブ

通常、シェルは、コマンドラインに指定されたすべてのファイル名パターンを、それにマッチするファイル名に展開する。これをグロブ(globbing)と言う。

例: ~/*.txt → ホームディレクトリにある全ての.txtファイル

Perlプログラムの中で、*.txtのようなパターンを展開するには、glob関数を使う。

my @all_files = glob '*';
my @txt_files = glob '*.txt';

Unixファイルシステムの基本(iノードとリンク)

  • 各ファイルは、番号が振られたiノード(inode)に格納される(ディスクを土地だと考えると、iノードは、その特定の1区画に相当)。
  • 各iノードはリンク数(link count)という数を持っている。iノードがどのディレクトリにも入っていなければ、リンク数は必ず0になる。iノードがディレクトリに追加されると、リンク数が1つ増やされる。
  • ls -lコマンドの出力で、パーミッションフラグ(-rw-r--r--等)の右隣りに表示されるのはリンク数。ほとんどのファイルは1、ディレクトリは最低でも2。
  • リンク(ハードリンク)を作成できるのは、ファイルのみ。ディレクトリは不可。
  • ボリュームをまたいでリンクを作成することはできない。

シンボリックリンク

シンボリックリンク(symbolic link)は、ディレクトリ内の特別なエントリで、システムに対して別の場所を見に行くように指示する。シンボリックリンクには、以下のような特徴がある。

  • シンボリックリンクでは、リンク数は増えない。
  • ディレクトリに別名をつけることができる。
  • ボリュームをまたいでシンボリックリンクを作成することができる。

ファイルテスト演算子(読み・書き・実行・存在):

#!/usr/bin/env perl
use v5.12;
use warnings;

# コマンドラインに指定されたファイル名のリストを受け取って、それぞれについて、
# 読み出し可能か、書き込み可能か、実行可能か、又は存在しないか、を表示するプログラム

foreach (@ARGV) {
    say "file: $_";
    if (-r) { # ファイルが読み込み可能か
        say "readable";
    } else {
        say "not readable";
    }

    # 同じファイルに対する2回め以降のファイルテストでは、
    # 「_」を使うと1回めに取得した結果を再利用するので、パフォーマンスが良くなる
    if (-w _) { # ファイルが書き込み可能か
        say "writable";
    } else {
        say "not writable";
    }
    if (-x _) { # ファイルが実行可能か
        say "executable";
    } else {
        say "not executable"
    }
    if (-e _) { # ファイルが存在するか
        say "exists";
    } else {
        say "not exists";
    }
    print "\n";
}

最終更新日時:

#!/usr/bin/env perl
use v5.12;
use warnings;

# コマンドラインに指定されたファイル名のリストを受け取って、
# そのうち最も古いファイルの名前とその古さを日数単位で表示するプログラム

die "No file names supplied!\n" unless @ARGV;
my $oldest_name = shift @ARGV;
my $oldest_age = -M $oldest_name; # -M でファイルの最終更新日を取得

foreach (@ARGV) {
    my $age = -M;
    ($oldest_name, $oldest_age) = ($_, $age)
        if $age > $oldest_age;
}

printf "The oldest file was %s, and it was %.1f days old.\n", $oldest_name, $oldest_age;

ファイルテスト演算子を重ねて使う(Perl v5.10以上):

#!/usr/bin/env perl
use v5.12;
use warnings;

say "Looking for my files that are readable and writable";
die "No files specified!\n" unless @ARGV;

foreach my $file ( @ARGV ) { # -o:所有している
    say "$file is readable and writable" if -o -r -w $file;
}

モジュール内の特定のサブルーチンだけインポートする:
#!/usr/bin/env perl
use v5.12;
use warnings;
use File::Basename qw/ basename /; # リストで指定

my $name = "/usr/local/bin/perl";
say basename $name;
日付の操作はDateTimeモジュールで:
#!/usr/bin/env perl
use v5.12;
use warnings;
use DateTime;

my $now = DateTime->now();

my $y = $ARGV[0];
my $m = $ARGV[1];
my $d = $ARGV[2];

my $user = DateTime->new(year => $y, month => $m, day => $d);

my $duration = $now - $user;

my @units = $duration->in_units( qw(years months days));
printf "%d years, %d months, and %d days", @units;

if/unless/while/until/foreach等は、「修飾子」にできる:
#!/usr/bin/env perl
use v5.12;
use warnings;

my @array = (1, 2, 3);
say foreach (@array);
ブロックスコープ:
#!/usr/bin/env perl
use v5.12;
use warnings;

{
    print "Please enter a number: ";
    chomp(my $n = );
    my $root = sqrt $n; # $root はこのブロック内でのみ有効な変数
    say "The square root of $n is $root";
}

last/next/redo:

  • for/foreach/while/until/裸のブロックから抜け出せる
  • if/until/サブルーチンブロックからは抜け出せない
例:
#!/usr/bin/env perl
use v5.12;
use warnings;

foreach (1..10) {
    print "Iteration number $_.\n\n";
    print "Please choose: last, next, redo, or none of the above? ";
    chomp(my $choice = );
    print "\n";
    last if $choice =~ /last/i;
    next if $choice =~ /next/i;
    redo if $choice =~ /redo/i;
    print "That wasn't any of the choices... onward!\n\n";
}

print "That's all, folks!\n";
defined-or演算子(左辺が未定義なら右辺の値を返す):
#!/usr/bin/env perl
use v5.12;
use warnings;

my %last_name;
my $last_name = $last_name{'someone'} // '{No last name}';
say $last_name;

#!/usr/bin/env perl
use v5.12;
use warnings;

$_ = 123456789;

s/
(?<=[0-9]) # 前に1文字以上の数字があり
(?=(?:[0-9]{3})+ # 後ろに3文字の数字のセットが1個以上あり
$) # 後ろに余計なものが続かない位置にマッチ
/,/gx; # マッチした位置にカンマを挿入
say; # 123,456,789

$_ = 12345678;
s/(?<=[0-9])(?=(?:[0-9]{3})+$)/,/g;
say; # 12,345,678
上記正規表現は、『詳説 正規表現 第3版』p.62より

詳説 正規表現 第3版
Jeffrey E.F. Friedl
オライリージャパン
2008-04-26

このページのトップヘ