Perl

Perlはテキスト処理に秀でたスクリプト言語。
sedやawk、grepといったツールの代替として使うことで、環境依存性の少ないスクリプトが簡単に書ける。

歴史ある言語であるが、最近はRubyやPythonの勢いに吞まれている雰囲気。
Perlと比べるとPythonは全然違う方向性、RubyはPerlと同系統という感じ。
たとえばPerlの有力な使い途の一つにワンライナーがあるが、Pythonでワンライナーなどとても書けたものではないのに対し、RubyはコマンドラインオプションまでPerlに寄せていたりする。

Perlのオブジェクト指向は後付けであるため、最初からオブジェクト指向で作られた言語と比べると便利ではない(が、それはライブラリを作るのが難しくなるだけであって、単純にライブラリを使うだけなら難しくないという印象)。ただ、オブジェクト指向前提でない分ちょっとしたスクリプトを書くだけならシンプルに書けて良い気がする。

テストやドキュメントをきちんと書く文化がある世界であるらしく、こういった面も非常にありがたい。特に、言語機能からCPANで入れたモジュールまでほとんどのドキュメントがperldocコマンドを打つだけで気軽に端末で読めるのには感動した。こういう環境が他の言語にもあってほしいと願うばかりである。

私はPerlを使うようになって日が浅いのだが、すぐに好きになってしまった。言語自体の魅力のためだけではなく、開発者ラリー・ウォールの文章に惚れ込んでしまったせいかもしれないが。

リンク

インストール

ほとんどのUnix系環境に最初から入っている(OSの諸々のスクリプトがPerlで書かれている為)ので、軽く使うだけならばそれを使えば良い。

ただ、外部モジュールを入れようとか考え始めると逆にOSを壊さないか心配になってくるので、plenv を使ってローカルにインストールするのがおすすめ。

モジュールのインストールには cpanm (cpanminus)を使うのが良い。plenvを使う際は plenv install-cpanm として cpanm をインストールする。

WindowsではWSLを使えば良いと思うが、Strawberry Perlのように Windowsネイティブで動くものもある。

スクリプトの雛型

#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
use utf8;

say "Hello, world!";

とりあえずこれを最初に書いておけというおまじない。スクリプトはUTF-8で保存する。

ただ、これだとWindowsでコマンドプロンプトを使っている環境では文字コードまわりの警告が出る。
Encode::Locale というモジュールを入れて以下のようにしておくと、端末のエンコードに依存せず問題なく表示(及び入出力)できるはず。

#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
use utf8;
use open ':encoding(UTF-8)';
use Encode::Locale;
binmode(STDIN, ":encoding(console_in)");
binmode(STDOUT, ":encoding(console_out)");
binmode(STDERR, ":encoding(console_out)");
Encode::Locale::decode_argv;

say "日本語表現";

ドキュメントの読み方

コンソールからperldocコマンドでドキュメントが読める。

$ perldoc perl # 言語とドキュメントの概要
$ perldoc perlintro # 初心者向けの入門記事
$ perldoc perlrun # 'perl' コマンドのオプション等の解説
$ perldoc perltoc # 各ドキュメントの目次

perldoc perltocはかなり詳細まで書かれているので、何を見ればよいかわからないときはまずperldoc perlの最初のほうに書かれている簡単な内容紹介を眺めるのがおすすめ。

各種モジュールのドキュメントも同様にperldocコマンドで読める。例えばLWP::Simpleモジュールのドキュメントが読みたい場合は

$ perldoc LWP::Simple

で良い。

perldocの色付け

Pod::Text::Color::Delight というモジュールを入れた上で perldoc -MPod::Text::Color::Delight perlのように呼び出すと色がついてとても読みやすくなるのでおすすめ。

.bashrcなどに

export PERLDOC="-MPod::Text::Color::Delight"

と書いておくと自動で読み込んでくれる。

cpandoc

perldocはインストール済みのモジュールのドキュメントしか読めないが、cpandocというモジュールを入れるとperldocと同じ使い勝手でcpan上の任意のモジュールのドキュメントが読めるようになるので便利。

$ cpanm Pod::Cpandoc
$ cpandoc Task::Kensho

コメント

# 1行コメント

=begin comment
複数行コメントはこのように begin coment と cut で挟む。
これは POD(Plain Old Documentation) というPerlのソースコードにドキュメントを埋め込む書式を利用したもの。
=cut

ファイル入出力

# ファイルハンドルの作成
open(my $in,  "<",  "input.txt")  or die "Can't open input.txt: $!";
open(my $out, ">",  "output.txt") or die "Can't open output.txt: $!";
open(my $log, ">>", "my.log")     or die "Can't open my.log: $!";

# 一行ずつ読み込んで処理
while (my $line = <$in>) {
    chomp $line; #$lineには末尾の改行が含まれるのでそれを削除
    say "今読んだ行: $line";
}

# printやsayにファイルハンドルを渡すとそこに書き込める
print STDERR "This is your final warning.\n";
print $out $record;
say $log $logmessage;

# ファイルハンドルを閉じる
close $in or die "$in: $!";
close $out or die "$out: $!";
close $log or die "$log: $!";

外部コマンド(別プロセス)実行

注意:ここではセキュリティのことを考えなくてもよい場合(信頼できる人だけが叩くスクリプトを作る場合)を扱います。CGIなど、不特定多数の人の入力をもとにコマンドを実行する場合はここに書かれていない諸々のセキュリティ上の注意が必要です。

system()

起動するだけなら system() でよい。

system("ls");

標準出力をとる

標準出力をとりたいならバッククオートを使う。

my $output = `ls`;
print "Output: $output";

標準出力といっしょにエラー出力をとる

バッククオートの中にリダイレクトを書けばよい。

my $output = `gcc 2>&1`;
print "Output: $output";

標準入出力を両方使う

この場合openではできないので IPC::Open2 を使う。

なお、標準エラー出力も扱いたい場合は IPC::Open3 を使う(IPC::Open2はIPC::Open3のラッパーである)。

use Encode::Locale;
use IPC::Open2;

# 両方向のストリームを開く
open2(*README, *WRITEME, "cat -"); # cat - は標準入力の内容をそのまま標準出力に返すコマンド

# 文字コードを指定(非ASCII文字を入出力する場合に必要)
binmode(README, ":encoding(console_in)");
binmode(WRITEME, ":encoding(console_out)");

# 標準入力に流し込み
say WRITEME "こんにちは";
say WRITEME "さようなら、\nまた逢う日まで";
close WRITEME;

# 標準出力の結果を得る
while(<README>){
  print "> " . $_;
}
close README;

正規表現

マッチ

=~ を使えば正規表現マッチができる。

my $str = <STDIN>; #標準入力から入力
if($str =~ /hoge.+/){
  say "hogeから始まっています";
} else {
  say "hogeから始まっていません";
}

置換

$str =~ s/前/後/ でできる。

$str =~ s/hoge/fuga/;
print $str;

非破壊で置換したいときは、s///rを使う。

my $new = $str =~ s/hoge/fuga/r;
print $str;
print $new;

コマンドラインオプションの解析

標準ライブラリ Getopt::Long を使うのがお手軽。

use Getopt::Long qw(:config posix_default no_ignore_case);

GetOptions(
  \my %opt, qw/
    arch=s
    n=i
  / # sは文字列、iは整数
);

# 必須オプションの処理
if(!exists $opt{arch}) {
  die 'please set --arch=x86 or --arch=x86_64';
}

my $n = $opt{n} // 24; # 指定されなかったらデフォルト値を使う場合

# perl hoge.pl --arch=x86 --n=12

Imager

画像を扱うライブラリ。
Perl/Imager 参照。

GUI(Perl/Tk)

GUIライブラリにもいろいろあるが、一番お手軽なのはPerl/Tkだろうか。

$ cpanm Tk

でインストールでき、

#!/usr/bin/perl -w 
use utf8;
use Tk;
use strict;

my $mw = MainWindow->new;
$mw->optionAdd( '*font' => 'MSゴシック 12' );
$mw->Label(-text => 'こんにちは世界!')->pack;
$mw->Button(
    -text    => 'Quit',
    -command => sub { exit },
)->pack;
MainLoop;

といった感じで使える。

exe化

PAR::Packerで簡単にexe化できる。

インストール

Strawberry Perlなら

$ cpanm PAR::Packer

でインストールできる。
ネット上にはインストールに失敗するという記事も書かれているが、Strawberry Perl v5.28.2 + PAR::Packer 1.050の私の環境では、時間はかかったがテストもきちんと通りインストールに成功した。

使い方

$ pp -o hoge.exe hoge.pl

だけで1ファイルのexeになる。依存しているモジュールもModule::ScanDepsを使った解析によって自動で含めてくれる。
Perl/Tkなどを使ったGUIアプリで黒い画面を出したくない場合は --gui オプションをつければ良い。

なお、一時ファイルとして処理系を展開してから実行するらしく(参照: Strawberry Perl(Portable)でPerlスクリプトのexeファイル化 | ビビビッ)、exeの初回起動は少し時間がかかる。

メールを送る

例えばGmailでメールを送るには以下のようにする(2020年10月現在)。

cpanm Email::Stuffer MIME::Base64 Authen::SASL Term::ReadKey
#!/usr/bin/env perl
use strict;
use warnings;
use 5.024;
use utf8;
use open ':encoding(UTF-8)';
use Encode::Locale;
binmode(STDIN, ":encoding(console_in)");
binmode(STDOUT, ":encoding(console_out)");
binmode(STDERR, ":encoding(console_out)");
Encode::Locale::decode_argv;

use Email::Stuffer;
use Email::Sender::Transport::SMTP;

# 本文
my $subject = 'Perlからのメール送信テスト';
my $body = <<'BODY_END';
これはサンプルめっせーじです!
なんとPerlからメールが送れちゃうんです!
BODY_END

# SMTPアカウント設定
my $sasl_password = prompt_for_password('Gmailのパスワード: ');
my $transport = Email::Sender::Transport::SMTP->new(
    host => 'smtp.gmail.com',
    ssl => 'starttls',
    sasl_username => 'example@gmail.com', # 送信元
    sasl_password => $sasl_password,
);

# 送信
Email::Stuffer
->from('example@gmail.com') # 送信元
->to('tim@example.com') # 宛先
->subject($subject)
->text_body($body)
->transport($transport)
->send;

# パスワードをユーザーに聞くサブルーチン
sub prompt_for_password {
    my $message = shift;
    require Term::ReadKey;
    Term::ReadKey::ReadMode('noecho');
    print $message;
    my $password = Term::ReadKey::ReadLine(0);
    Term::ReadKey::ReadMode('restore');
    print "\n";
    $password =~ s/\R\z//; # 改行の除去
    return $password;
}

最終更新: 2020-10-25 02:55:42 +0900

[Top]

This page is generated by sinanoki.