更新日:
投稿日:

PerlのクラスはPythonみを感じる奥ゆかしい作りになっている。

ファクトリ関数でオブジェクトを生成して、そのオブジェクトの参照を引き回すことで実現してる感じ。

確認環境

Env Ver
Perl 5.34.0

基本

ファイル拡張子は.pmが一般的だと思われる。ファイル名とクラス名がリンクしているためPath/To/UpperCamel.pmが多分いい

ハッシュに突っ込んでいく方式

# これがクラス名になる。PATH::TO::NAME構文で書く
package Example;

use strict;

# コンストラクタ
# 第一引数にはpackageのフルパスが入り、第二引数以降に通常引数が入る
sub new {
  # 祝福することでインスタンスオブジェクトを生成できる
  my $self = bless({}, shift);
  # フィールドに値を突っ込む。これがプロパティになる。アクセサはない
  $self->{hoge} = shift;
  $self->{piyo} = shift;

  # インスタンスを返す
  return $self;
}

# メソッド
# 第一引数にはインスタンスオブジェクトが入る。アクセサはない
sub get_hoge {
  my $self = shift;
  return $self->{hoge};
}

1;

オブジェクト生成時にアサインする方式

package Example;

use strict;

sub new {
  my ($class, @args) = @_;
  my $self = bless({
    hoge => shift @args,
    piyo => shift @args
  }, $class);

  return $self;
}

sub get_hoge {
  my $self = shift;
  return $self->{hoge};
}

1;

クラスインスタンスの生成

ディレクトリ構成

├─library
│  └─Example.pm
└─main.pl

コード

クラスのコードは前述の内容

use strict;
# useするモジュールのパスを指定するおまじない
# パスにはクラスファイルを格納している根本のパスを指定する
# 標準モジュールは区別されるようで、この行の下にuse IPC::Open2;とか書いても、ちゃんと本来のモジュールが読み込まれる
use lib './library';

use Example;

# コンストラクタ呼び出しは()で囲まないとエラーになる
my $ex = Example->new("aaaa", 123);
print $ex->{hoge}."\n";
print $ex->{piyo}."\n";
print $ex->get_hoge."\n";

継承

基底クラス

package Example;

use strict;

sub new {
  my $self = bless({}, shift);
  $self->{hoge} = shift;
  $self->{piyo} = shift;

  return $self;
}

sub get_hoge {
  my $self = shift;
  return $self->{hoge};
}

1;

子クラス

package ExampleChild;

use strict;
use parent 'Example';

sub new {
  my ($class, @args) = @_;

  my $self = $class->SUPER::new(shift @args, shift @args);
  $self->{fuga} = shift @args;
  return $self;
}

1;

あとがき

仮引数を名前付きで取るかshiftで取るかは微妙に悩む。shiftの方がPerlらしい気もするし、変数名を変更するときの手間を考えると楽ではある。しかしshiftは読みづらいし、名前付き変数を列挙したほうが読みやすい気もする。

今回Perlをある程度書いてみた感じ、Perlはかなり書き方が自由に感じたし、そこはかなり楽しかったが、コーディング規約という面で見ると自由すぎると困る部分もあるし、判り易いほうがいいのでshiftは避けたほうがよさそうだ。

しかし普段JSを書いたりしている中で、クラスとは新しいオブジェクトを返す関数なのでは?と思っていたので、その辺りの解像度が上がったのは良かった。

参考

ぶっちゃけまともにPerlを書くのはこれが初めてなので、クラスとは直接関係ないサイトもある。

perldoc.jpは公式ドキュメントの日本語訳らしい。今も更新されている。

更新日:
投稿日:

base64みたいなコマンドを使いたい時に

確認環境

Env Ver
Perl 5.34 .0

サンプルコード

バッククォートでコマンドを括り、後はシェルスクリプト度同じ理論で書くと行ける

# base64エンコードされた文字列
my $input = 'Kipib2xkKioKKml0YWxpYyoKfn5zdHJpa2V+fgotIGxpCiAgLSBzdAp8VEF8QkxFfAp8LS18LS0tfAp8YWF8YmJifAp8Y2N8ZGRkfAo=';
# 変数を標準出力に展開し、base64の標準入力として使い、base64コマンドの標準出力を戻り値の変数に格納している
my $output = `echo $input | base64 -d`;

print $output;

出力

**bold**
*italic*
~~strike~~
- li
  - st
|TA|BLE|
|--|---|
|aa|bbb|
|cc|ddd|

ダメだったコード

その1

# 標準ライブラリからopen2を取得
use IPC::Open2 qw/open2/;

my $pid = open2 *READ, *WRITE, 'base64 -d';
# base64エンコードされた文字列
print WRITE 'Kipib2xkKioKKml0YWxpYyoKfn5zdHJpa2V+fgotIGxpCiAgLSBzdAp8VEF8QkxFfAp8LS18LS0tfAp8YWF8YmJifAp8Y2N8ZGRkfAo=';
close WRITE;
my $output = <READ>;
close $READ;
waitpid $pid, 0;
print $output;

出力

何故か一行目しか出ない

**bold**

その2

# 標準ライブラリからopen2を取得
use IPC::Open2 qw/open2/;

my $pid = open2 my $reader, my $writer, 'base64 -d';
# base64エンコードされた文字列
print $writer 'Kipib2xkKioKKml0YWxpYyoKfn5zdHJpa2V+fgotIGxpCiAgLSBzdAp8VEF8QkxFfAp8LS18LS0tfAp8YWF8YmJifAp8Y2N8ZGRkfAo=';
close $writer;
my $output = <$reader>;
close $reader;
waitpid $pid, 0;
print $output;

出力

何故か一行目しか出ない

**bold**

参考

更新日:
投稿日:

文字列を編集したりするのに大変便利なやつ。sedやawkの代わりに使える。構文はPerlそのものが使える。なにせPerlなので

コマンドラインオプション

  • -e
    • ワンライナーでコードを書くやつ
    • php -rnode -eと同じ
    • Evaluate, Eval, 評価
  • -n
    • 入力の各行に対し処理がかかる
    • $.で行番号、$_で行の文字列を取得できる
    • while (<>)相当の処理
  • -p
    • 入力の各行に対し処理を行い、更にprint $_相当の処理を実行する
  • -l
    • 入力($_)から改行文字を削除し出力に改行を追加する
  • -a
    • 入力の各行に対してawk相当の文字列分割処理を行う(autosplit mode with -n or -p)
    • 分割した文字は$Fに配列として入るので次のようにして取得できる
      • perl -ale 'print "$F[0] - $F[1]'
    • $#Fを指定すると分割した個数が取れる
  • -F/pattern/
    • -aでsplitするパターンを設定する
    • 例えば-F,とするとCSVを分割できる
  • -i[ext]
    • ファイルを編集する
    • 使用例:perl -i -pe 's/aaa/xxx/' foo.txt
    • -i.bakのように指定するとバックアップファイルが作成される
    • このオプションは次に続く文字が解釈されるため、単体で指定する必要がある(-ipeのようには使えない)

構文

変数を指定しない場合、基本的に$_として扱われる

  • print
    • 標準出力に出力
    • 単体ではprint $_と同じ挙動をする
  • $hoge =~ s/foo/bar/
    • fooをbarに置換
  • /(.+)/; print $1
    • キャプチャした内容を出力
    • コマンド例:echo hoge.jpg | perl -ne '/(.+)./; print $1'
  • $_
    • 基本的に書かなくても補完される
    • 例えばecho aaabbc | perl -ne 's/c/d/; print'の出力はaaabbdとなる
    • その他特殊変数:https://perldoc.jp/docs/perl/5.18.1/perlvar.pod
  • END{}
    • このブロックで囲んだコードは実行時の最後に動作する
      • -n, -pを指定した場合、END{}$_が取れないので渡す場合は$x = $_; END{ print $x }のように別の変数に代入する必要がある
    • https://perldoc.jp/docs/perl/5.38.0/perlmod.pod#BEGIN44-32UNITCHECK44-32CHECK44-32INIT32and32END

チートシート

変数置換

一例

ls -l | perl -ale '$F[8] =~ s/\.html//; print $F[8];'

特定行を取得

1のところが行数なので、ここを変えることで任意の行の文字列を取れる

入力

cat <<EOF | perl -ne 'print if $. == 1'                                                                                                            25-08-10 - 14:48:39
aaa
bbb
ccc
EOF

出力

aaa

捕獲処理

入力

echo "foo bar" | perl -ne '/^([^ ]+)/; print $1'

出力

foo

名前付き捕獲

入力

echo "foo bar" | perl -pe 's/(?<first>.+) (?<last>.+)/$+{first}-$+{last}/'

出力

foo-bar

逆順出力

unshiftで配列の先頭に値を追加し、END{}で最後に出力している

入力

cat <<EOF | perl -ne 'unshift @x, $_; END{ print @x }'
aaa
bbb
ccc
EOF

出力

ccc
bbb
aaa
更新日:
投稿日:

文字コードはiso-2022-jp

SMTPの設定例

export EMAIL_SENDER_TRANSPORT=SMTP
export EMAIL_SENDER_TRANSPORT_host=smtp.example.com
export EMAIL_SENDER_TRANSPORT_port=1025

サンプルコード

use strict;
use Email::MIME;
use Email::MIME::Creator;
use Email::Sender::Simple qw(sendmail);

my $subject = Encode::encode('MIME-Header-ISO_2022_JP', 'さぶじぇくと');
my $mail    = Email::MIME->create(
    'header' => [
        'From'    => Encode::encode('MIME-Header-ISO_2022_JP', 'foo@example.com'),
        'To'      => Encode::encode('MIME-Header-ISO_2022_JP', 'to@example.com'),
        'Subject' => $subject,
    ],
    'attributes' => {
        'content_type' => 'text/plain',
        'charset'      => 'ISO-2022-JP',
        'encoding'     => '7bit',
    },
    'body' => Encode::encode('iso-2022-jp', 'ほんぶん!'),
);