Perl初めて触れた
Perlってなに?というはなしは色んな所でされているので割愛する。
ちょっとお仕事で触ることがあったので Perl v5.10.1
で開発をした際に調べたことをまとめた。
エンハンス的な案件だったので限定的な機能しか触ってない。なので、解説も限定的なのでご了承ください。
基礎的で特徴的なところ
身もふたもないけど wikipedia 見たほうが早いかもしれない。
変数名のルール
変数名 | ルール |
---|---|
$obj |
スカラ型の値、オブジェクトのインスタンスを格納する場合は、変数名の前に $ をつける。配列、ハッシュ(連想配列)の要素にアクセスする場合も使用する。 |
@arry |
配列型の値を格納する場合は、変数名の前に @ をつける。 |
%hash |
ハッシュ(連想配列)の値を格納する場合は、変数名の前に % をつける。 |
$
, @
, %
はシジルというらしい。
シジルの前に \
をつけると、リファレンス型をスカラ値として値を取り出せる。
リファレンス型のスカラ値はシジルをつけてアクセスすると実体を取り出せる。
※ wikipedia 参照。
変数宣言について
変数宣言方法 | 効果 |
---|---|
$v = 123 |
大域変数として宣言する |
local $v = 123 |
動的スコープで、ブロック内のみで有効な局所変数として宣言する。 |
my $v = 123 |
静的スコープで、ブロック内のみで有効な局所変数として宣言する。 |
my
はPerl5.0から登場したもので、それ以来 local は非推奨らしい。
※ wikipedia: Perl 参照
関数呼び出しについて
Perlでは関数じゃなくて サブルーチン という。
Rubyと同じ感覚でいける。下記2つは同じ。
open my DATA, "filename.txt";
print DATA;
open(my DATA, "filename.txt");
print DATA;
違いがわからないが、下記の記述方法もある。
&open(my DATA, "filename.txt");
引数がない場合は、カッコなしでもいいっぽい。
&doSomething;
関数ポインタに対して実行してる感じなのかな??
条件分岐
Ruby と同じ感覚でいける。
if ($v < 123) {
print "$v is under 123 (" . $v . ")";
} elsif ($v eq 123) {
print "$v is 123";
}
条件式の後置ができる。
print "$v is under 123 (" . $v . ")" if ($v < 123);
if の反転、unless
がある。
print "$v is not 123 (" . $v . ")" unless ($v == 123);
プロパティ、メソッドアクセス
PHPっぽい、->
を使用する。
my $ua = LWP::UserAgent->new;
$ua->agent("Dummy User Agent.");
コマンドライン上からプログラムを実行する
perl -M<リンクするモジュール> -e 'プログラム'
上記の構文を使ってモジュールがインストール済みか確認するようなコードがよく見られる。
インストールされていないモジュール Furl のインストール確認だと下記のようになる。
$ perl -MFurl -e "Furl"
Can't locate Furl.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .).
BEGIN failed--compilation aborted.
インストールされているモジュールだと下記のように何も出力されない。
$ perl -MLWP -e "LWP"
$
※ FurlとLWPはどちらも通信系のモジュール。
後述のモジュールのアンインストールはコレを使う。
パッケージ・モジュール管理
パッケージ管理には CPAN を使用する。
使用するユーザのホームディレクトリに配置されたりする。
ユーザローカルにコンテンツルートを設定していて、cpanもユーザローカル配下においてある場合は下記のような実装が必要かも。
use lib "/home/vagrant/perl5/lib/perl5";
use URI;
$url = URI->new('https://<なんかしらのエンドポイント>');
他にもいろいろやり方はあるっぽい。
上記自体は、パスが変わると使えなくなるのであまりおすすめできない。
おまけ
ほかにあるいろいろについて。
いろいろと言ってもやることは、ライブラリのサーチパスを設定すること。
ライブラリのサーチパスは @INC
という変数と、 PERL5LIB
という環境変数に入っているらしい。
$ perl -e "print @INC;"
/usr/local/lib64/perl5/usr/local/share/perl5/usr/lib64/perl5/vendor_perl/usr/share/perl5/vendor_perl/usr/lib64/perl5
設定のしかた、apacheで動かす上で反映させる方法は未調査。
インストール
$ cpan install <モジュール>
でモジュールを取り込む。
$ cpan <モジュール>
で実際にコンパイル?インストール?するという流れっぽい。
下記のように、cpanコンソールを使用することもできる。
$ cpan
Terminal does not support AddHistory.
cpan shell -- CPAN exploration and modules installation (v1.9402)
Enter 'h' for help.
cpan[1]>
help 出すと下記のようになる。
cpan[1]> help
Display Information (ver 1.9402)
command argument description
a,b,d,m WORD or /REGEXP/ about authors, bundles, distributions, modules
i WORD or /REGEXP/ about any of the above
ls AUTHOR or GLOB about files in the author's directory
(with WORD being a module, bundle or author name or a distribution
name of the form AUTHOR/DISTRIBUTION)
Download, Test, Make, Install...
get download clean make clean
make make (implies get) look open subshell in dist directory
test make test (implies make) readme display these README files
install make install (implies test) perldoc display POD documentation
Upgrade
r WORDs or /REGEXP/ or NONE report updates for some/matching/all modules
upgrade WORDs or /REGEXP/ or NONE upgrade some/matching/all modules
Pragmas
force CMD try hard to do command fforce CMD try harder
notest CMD skip testing
Other
h,? display this menu ! perl-code eval a perl command
o conf [opt] set and query options q quit the cpan shell
reload cpan load CPAN.pm again reload index load newer indices
autobundle Snapshot recent latest CPAN uploads
アンインストール
削除時に cpan は使用しない。
※ cpanm というコマンドでは削除ができるらしい。
# 削除対象のモジュールに関連するファイルの確認。
perl -MConfig -MExtUtils::Install -e '($FULLEXT=shift)=~s{-}{/}g; uninstall "$Config{sitearchexp}/auto/$FULLEXT/.packlist", 1, 1' Furl
# 削除を実行する。
perl -MConfig -MExtUtils::Install -e '($FULLEXT=shift)=~s{-}{/}g; uninstall "$Config{sitearchexp}/auto/$FULLEXT/.packlist", 1' Furl
ワンライナーでアンインストール事項してるだけ。
perlのプログラムでパッケージ操作するのね・・。
参考
cpan と cpanm
「CPANからモジュールを取得、アンパック、インストールする」ためのコマンドラインツールとのこと。
備考
Macだと brew install cpanminus
でインストールできるっぽい。
参考
構文
エラー処理
<なんか処理> or die
or
は、論理演算子の or で、||
と機能自体は同じだが、優先順位が違う。
※ とはいえ、 || die
にしてもだいたい問題なく動くらしい。
die
は、標準エラーに引数が渡されていれば、それの値を出力して処理を終了する関数。
イメージ的には下記のような感じかな。
sub die {
print 'args to stderr';
exit;
}
エラー出たらログに吐いて捨てるようなときによく使うっぽい。
Macに導入する
使ったことはないが、Ruby で言う rbenv 的な plenv
がある。
anyenv で管理可能らしい。
通信する
通信する際に使用するモジュールは前述の LWP
と Furl
が一般的。
サーバのモジュール構成を操作できない環境だと LWP
のほうが安泰っぽい。
LWP の使い方ざっくり
なんかしらのエンドポイントに対してパラメータ key1=value1
を付与して GETでリクエストを送る。
use LWP::UserAgent;
use URI;
$url = URI->new("https://なんかしらのエンドポイント");
$url->query_form("key", "value");
my $ua = LWP::UserAgent->new;
$ua->agent("Dummy User Agent");
my $response = $ua->get($url);
if ($response->is_success) {
# success;
} else {
# failed;
}
リクエストを送るのがユーザエージェントであるというのがちょっと面白いなと思った。
HTTPS のサーバにリクエストを送信する
HTTPSのサーバにリクエストをする際は、下記のモジュールが必要。
-
LWP::Protocol::https
※ LWPを使用する場合。 Net::SSL
SELinux問題
下記のようなエラーが出ることがある。
500 Can't connect to www.google.com:443 (Permission denied) Content-Type: text/plain Client-Date: Fri, 27 Jul 2018 18:18:17 GMT Client-Warning: Internal response Can't connect to www.google.com:443 (Permission denied) Permission denied at /usr/local/share/perl5/LWP/Protocol/http.pm line 50.
コレ自体は LWP も Furl も出る。
SELinuxが有効だとPermission Deniedが発生する。
※ SELinuxを適切に設定する方法・・・。
突貫対応なら、下記を実行すればとりあえず動くはず。
$ sudo setenforce 0
$ getenforce # 確認。Permissiveになっていれば、Permission Deniedが出ないはず。
JSON デコードざっくり
API呼び出してJSONもらってパースして・・・なんてよくあるケースですしね。
ついでに Furl ざっくり。
※ サンプルは Furl で通信した結果のレスポンスボディをJSONとしてパースするもの。
※ Encode, Furl, JSON をインストールしておく。
JSONモジュールの from_json
をすることでハッシュが取得できる。
use Encode;
use Furl;
use JSON;
$url = URI->new('https://<なんかしらのエンドポイント>');
$url->query_form('key1', 'value1');
$furl = Furl->new(
agent => 'Mozilla',
timeout => 25
);
$response = $furl->get($url);
if ($response->is_success) {
$body = decode_utf8($response->content);
$result = from_json($body);
if ($result->{'success'}) {
print 'success!!';
} else {
print 'failed';
}
} else {
print 'failed';
}
所感
思いの外ちゃんとした言語だった。
日本の方が開発したモジュールが結構あって、ちょっと感動した。
記事がやたらと古い。そして、エンジニア向けっぽくない記事が多い気がした。
情報がまとまってる場所もあまりない気がした。
perl書くんだけど、ファイルの拡張子は cgi だったり、cfgだったりしてちょっと混乱した。
フレームワーク慣れしてるととっつきにくい気がする。(ってのはCGIに関する感想かも)
perlといえば!な正規表現を今回触れることがなく、解説することができなかった。まぁ、そこら辺は多くの人がまとめてくれてるんじゃないかしら。