perl

この記事は現役ウェブディベロッパーがわかりやすさにこだわって作成しました

はじめに

 

このページはPERL学習のために個人のメモとして作成しました。

また様々なサイトで公開されている使えるノウハウやチップスもここで参照できるようにしました。

内容に不都合や問題がございましたらこちらまでご連絡ください。

 

Perlとは

Perl(パール)とは、ラリー・ウォールによって開発されたプログラミング言語である。実用性と多様性を重視しており、C言語sedawkシェルスクリプトなど他のプログラミング言語の優れた機能を取り入れている。ウェブ・アプリケーション、システム管理、テキスト処理などのプログラムを書くのに広く用いられている。

言語処理系としてのperlはフリーソフトウェアである。Artistic LicenseおよびGPLのもとで配布されており、誰でもどちらかのライセンスを選択して利用することができる。UNIXWindowsなど多くのプラットフォーム上で動作する。

Wikipediaより引用

 

 

 

処理を書く前に

まず、Perlで処理をさらさらーっと書く前に次の2行をファイルに書いておきます。

hello.pl
use strict;
use warnings;

基本的にこの2行はマストです。はい。
エラーをキャッチ&リリースしてくれるんですよ。
まあ、僕のようなPerl初心者に向けた優しいガイドのようなものです。

use strict

これは変数宣言してるかどうかなどを見てくれます。

例えば

hello.pl
use strict;

$hello = "Hello World!!!";

こう書いて処理を実行してあげると下記のようなエラーが吐き出されると思います。
Global symbol "$hello" requires explicit package name at hello.pl line 4.
ちゃんと変数宣言してください、と言われるので

hello.pl
use strict;

my $hello = 'Hello World!!!';

このように、myを付けてあげてください。
そうすれば、問題なく動作すると思います。

use warnings

バグの可能性の高いコードがあれば警告してくれます。
例えば

hello.pl
use warnings;

my $hello;
print $hello;

こう書いて処理を実行してあげると下記のような警告が吐き出されると思います。
Use of uninitialized value $hello in print at hello.pl line 6.

変数が未定義のものを使ってますよ、と警告をだしてくれます。
なので、変数に何か値を入れてあげれば問題なく動作します。

var_dump的なもの

変数の内容を見る方法があるようですね。
PHPでいうvar_dumpのようなものです。

hello.pl
use Data::Dumper;

#配列 ※詳細は後述
my $alphabet = ['a', 'b', 'c'];
#ハッシュ ※詳細は後述
my $fruit    = {'red' => 'アップル', 'yellow' => 'バナナ', 'green' => 'メロン'};

warn Dumper $alphabet;
warn Dumper $fruit;

#実行結果
$VAR1 = [
          'a',
          'b',
          'c'
        ];
$VAR1 = {
          'green' => 'メロン',
          'yellow' => 'バナナ',
          'red' => 'アップル'
        };

シンタックスチェック

プログラムを実行することなくシンタックスチェックをする方法があります。

$perl -cw file_name.pl

実行する前にひとまずこれで確認するといいでしょう。

 

 

 

変数

Perlの変数宣言には以下のものがあります。
PHPだとそんなに気にしなかったのですが(僕だけかしら)、Perlだとこうするんですね。
他の言語もこんな感じなのかな?

スカラ変数

スカラ変数には、文字列や数値を入れることができます。

profile.pl
my $name = 'アラシダ';
my $age = 26;

print "僕の名前は$nameです\n"; # 僕の名前はアラシダです
print "年齢は$age歳です\n"; # 年齢は26歳です

変数を展開する方法は他にもあります。

profile.pl
print "僕の名前は${name}です\n"; # 僕の名前はアラシダです
print "年齢は${age}歳です\n"; # 年齢は26歳です
profile.pl
print "僕の名前は" . $name . "です\n"; # 僕の名前ははアラシダです
print "年齢は" . $age . "歳です\n"; # 年齢は26歳です

スカラ演算子

もちろん、計算することもできます。

 構文例 名称説明
x + y加算x と y を足した値
x - y減算x から y を引いた値
x * y乗算x と y をかけた値
x / y除算x を y で割った値
x % y剰余x を y で割った余り
x ** y累乗x を y 乗した値
x++インクリメントx に 1 を足した値
x--  デクリメントx から 1 を引いた値

比較演算子

比較演算子はこちら。
数値と文字列で違いがあるとは知らなかったです。

 数値演算子 文字列演算子説明
x == yeqx と y が等しいなら真
x != ynex と y が等しくないなら真
x < yltx が y より小さければ真
x > ygtx が yより大きければ真
x <= ylex が y 以下なら真
x >= ygex が y 以上なら真

んー書いていると分からなくなってくるな。。
間違えていたらご指摘をm(_ _)m

配列変数

配列変数は、もうそのまんまです。配列をいれることができます。

ここでちょっと勘違いしてしまいそうなのですが、@fruit[1]ではなく、$fruit[1]になります。
ふむ。ややこしい。

fruit.pl
# 配列
my @fruit = ('アップル', 'バナナ', 'オレンジ');

# 表示
print "ぼくは$fruit[1]が好きです\n"; # ぼくはバナナが好きです

# 代入
$fruit[1] = 'メロン';

# 表示
print "ぼくは$fruit[1]が好きです\n"; # ぼくはメロンが好きです

配列操作

簡単な配列操作を見ていきます。

関数説明
shift先頭の要素を取り出す
unshift先頭に要素を追加
pop末尾の要素を取り出す
push末尾に要素を追加
sort配列の順序をソートする
reverse配列の順序を逆順にする
fruit.pl
my @fruit = ('アップル', 'バナナ', 'オレンジ');

# 先頭の要素を取り出す
my $apple = shift @fruit;

print "これは$appleです\n"; # これはアップルです
print "@fruit\n"; # バナナ オレンジ

# 先頭に要素を追加
unshift(@fruit, 'マスカット');

print "@fruit\n"; # マスカット バナナ オレンジ

# 末尾の要素を取りだす
my $orange = pop(@fruit);

print "$orange\n"; # オレンジ
print "@fruit\n"; # マスカット バナナ

# 末尾に要素を追加
push(@fruit, 'チェリー');

print "@fruit\n"; # マスカット バナナ チェリー

# 配列の順序をソートする
my @alphabet = ('C', 'A', 'D', 'B', 'E');
@alphabet = sort(@alphabet);

print "@alphabet\n"; # A B C D E

# 配列の順序を逆順にする
@fruit = reverse(@fruit);

print "@fruit\n"; # チェリー バナナ マスカット

配列の個数を取得することもできます。

fruit.pl
my @fruit = ('アップル', 'バナナ', 'オレンジ');
my $cnt = @fruit;

print "$cnt\n"; # 3

もっと他にもあるんですけど、基本的な部分はこんなところでしょうかね。

ハッシュ変数

ハッシュというのは、連想配列のことですね。「キー」と「値」がペアとして存在する配列です。
「%」で始まります。

アクセスの仕方は $変数名{'key'} です。
% でアクセスするのはないので間違えないようにしましょう。

fruit.pl
# ハッシュ
my %fruit = ('a' => 'apple', 'b' => 'banana', 'c' => 'cherry');

# 表示
print "$fruit{'a'}\n"; # apple

# 代入
$fruit{'a'} = 'apricot';

# 表示
print "$fruit{'a'}\n"; # apricot

ハッシュ操作

簡単なハッシュ操作を見ていきます。

関数説明
keysすべての「キー」を取り出す
valuesすべての「値」を取り出す
eachハッシュに含まれている要素を取り出す
exists指定したキーがハッシュに存在するかどうか
delete指定されたハッシュ要素を削除
fruit.pl
# ハッシュ
my %fruit = ('a' => 'apple', 'b' => 'banana', 'c' => 'cherry');

# keys
my @fruit_key = keys %fruit;

print "@fruit_key\n"; # 例 a b c

# values
my @fruit_val = values %fruit;

print "@fruit_val\n"; # 例 apple banana cherry

# each
my ($key, $val) = each %fruit;

print "$key : $val\n"; # 例 a : apple

# exists
exists $fruit{'a'}; # true
exists $fruit{'e'}; # false

# delete
delete $fruit{'a'}; 

print %fruit; # 例 b banana c cherry

実行結果に「例」と書いているんですが、返却値の順番にはばらつきがあります。
順番に値を取得して何か処理を書こうとすると思わぬハプニングが起こるかもしれませんのでお気をつけを。

どうしても順番に取得したいのであれば、モジュールを用意する必要があります。
しかし、今回は割愛させて頂きますm(_ _)m

foreach文でいこうか、でいいかもしれませんね。

each関数に関しては while文と使うことが多いかもしれません。

fruit.pl
# ハッシュ
my %fruit = ('a' => 'apple', 'b' => 'banana', 'c' => 'cherry');

# each
while (my ($key, $val) = each %fruit) { 
    print "$key : $val\n";
}

# 実行結果 例
a : apple
b : banana
c : cherry

リファレンス

リファレンスとは、値の代わりにアドレスを指し示すスカラ変数です。
んーなんだか難しい。
まあ、値が置いてある住所を見てるんだなーでいいと思います。

ひとまず、書いていきますね。

ref.pl
# スカラ
my $apple = 'apple';
# 配列
my @fruit_a = ('banana', 'strawberry', 'grape');
# ハッシュ
my %fruit_h = ("m" => "melon", "p" => "peach", "o" => "orange");


my $apple_ref = \$apple;
my $fruit_a_ref = \@fruit_a;
my $fruit_h_ref = \%fruit_h;

各変数の前にリファレンス演算子 \ を付けてあげます。
そうすると、各変数のアドレスを変数に対して入れてくれます。

これとは別に、リファレンスの作成方法があります。

ref.pl
# スカラ
my $apple_ref = \'アップル';
# 配列
my $fruit_a_ref = ['banana', 'strawberry', 'grape'];
# ハッシュ
my $fruit_h_ref = {"m" => "melon", "p" => "peach", "o" => "orange"};

こちらの方が楽ですし、見た目も綺麗ですね。

リファレンスから変数の値を参照するには、参照先の変数の識別子を変数の頭に付けます。
デリファレンス といいます。

ref.pl
print "$$apple_ref\n";
print "@$apple_a_ref\n";

while( ($key, $val) = each %$ref_hash ) {
    print "$key : $val \n";
}

# 実行結果
# スカラ
apple

# 配列
banana strawberry grape

# ハッシュ 例
o : orange
p : peach
m : melon

それぞれの要素に対して操作する場合は下記のようになります。

ref.pl
# 配列
my $fruit_a_ref = ['banana', 'strawberry', 'grape'];
# ハッシュ
my $fruit_h_ref = {"m" => "melon", "p" => "peach", "o" => "orange"};

# アクセス方法1
print "$$fruit_a_ref[0]\n";    # banana
print "$$fruit_h_ref{'m'}\n";  # melon

# アクセス方法2
print "$fruit_a_ref->[0]\n";   # banana
print "$fruit_h_ref->{'m'}\n"; # melon

# 代入
$$fruit_a_ref[0] = 'blueberry';
print "$$fruit_a_ref[0]\n";    # blueberry

$fruit_h_ref->{'m'} = 'musk melon';
print "$fruit_h_ref->{'m'}\n"; # musk melon

アクセス方法1と2は同じ意味です。書き方としては、後者の方がすっきりしてますね。
基本的にはアロー演算子の方がいいと思われます。

参照先のデータタイプを調べる関数がありますので一応ここで。

ref.pl
# スカラ
my $apple_ref = \'アップル';
# 配列
my $fruit_a_ref = ['banana', 'strawberry', 'grape'];
# ハッシュ
my $fruit_h_ref = {"m" => "melon", "p" => "peach", "o" => "orange"};

print ref $apple_ref;   # SCALAR
print ref $fruit_a_ref; # ARRAY
print ref $fruit_h_ref; # HASH

 

 

 

制御構文

条件文

if文

おなじみのif文です。基本的に意味は他の言語と同じかと思います。
else if ではなくて elsif というところだけ気をつければいいかなーて感じですかね。

control.pl
my $fruit = 'apple';

if ($fruit eq 'apple') {
    print "appleです\n"; 
} elsif ($fruit eq "middle") {
    print "appleではないです\n"; 
} else {
    print "もはやフルーツではありません\n"; 
}

# 実行結果
# appleです

unless文

if文とは反対の意味を持っており、「〜では無いとき」という意味になります。

control.pl
my $fruit = 'banana';

unless ($fruit eq 'apple') {
    print "appleではありません\n"; 
}

# 実行結果
# appleではありません

三項演算子

if文を短くしてくれるのが、三項演算子です。
簡単な処理の場合はこちらを使うほうがすっきりするかもしれませんね。

[条件式] ? 真の場合 : 偽の場合;

control.pl
my $fruit = 'apple';

print $fruit eq 'apple' ? "アップルです\n" : "アップルではありません\n";

# 実行結果
# アップルです

ループ文

while文

while文は、条件式が真の間、ブロック内を実行します。

control.pl
my $cnt = 0;
while ( $cnt < 10 ) {
    print "$cnt\n";
    $cnt++;
}

# 実行結果
0 1 2 3 4 5 6 7 8 9

$cntが10以下である場合、ブロック内が実行されているのがわかるかと思います。

until文

until文はwhile文の反対で、条件式が偽の間、ブロック内を実行します。

control.pl
my $num = 1;
until ($num > 10) {
    print "$num\n";
    $num++;
}

# 実行結果
1 2 3 4 5 6 7 8 9 10

for文

control.pl
for (my $i = 0; $i < 10; $i++) {
    print "$i\n";        
}

# 実行結果
0 1 2 3 4 5 6 7 8 9

foreach文

control.pl
my @fruit = ('banana', 'strawberry', 'grape');

foreach my $name (@fruit) {
    print "$name\n";
}

# 実行結果
banana strawberry grape

ループ制御

演算子説明
nextループをスキップする
lastループを終了する
redoループの先頭に制御を移す

next

ループをスキップさせるのが、nextです。
下記の場合 $cnt = 2 のとき処理をスキップさせるため、実行結果に 2 はありません。

control.pl
my $cnt = 0;

while ($cnt <= 5) {
    $cnt++;

    if ($cnt == 2) {
        next;
    }

    print "$cnt¥n";

    #next演算子が実行された場合、この位置に進む
}

# 実行結果
1 3 4 5 6

last

ループを終了させるのが、lastです。
下記の場合 $cnt = 3 のとき処理を終了させるため、実行結果に 3 以降はありません。

control.pl
my $cnt = 0;

while ($cnt <= 5) {
    $cnt++;

    if ($cnt == 3) {
        last;
    }

    print "$cnt\n";
}
#last演算子が実行された場合、この位置に進む

# 実行結果
1 2

redo

ループを先頭にスキップさせるのが、redoです。
下記の場合 $cnt = 6 のとき処理を先頭にスキップさせるため、実行結果に 7 が出力されます。
redoによってwhile文内の条件式を無視して先頭にスキップしているので、実行結果に 7 が出るわけです。
nextと似ていますが、挙動が別物なので気をつけないといけませんね。

control.pl
my $cnt = 0;

while ($cnt <= 5) {
    #redo演算子が実行された場合,この位置に進む
    $cnt++;

    if ($cnt == 6) {
        redo;
    }

    print "$cnt\n";
}
# 実行結果
1 2 3 4 5 7

 

 

 

サブルーチン

サブルーチンとは関数のことです。
sub サブルーチン名 { 処理 }といった形で書いていきます。
サブルーチンの呼び出し方法は&サブルーチン名()です。

hello.pl
&hello();

subhello {
    my $name = 'アラシダ';
    my $age = 26;

    print "僕の名前は$nameです\n"; # 僕の名前はアラシダです
    print "年齢は$age歳です\n"; # 年齢は26歳です
}

引数の渡し方は下記のようになります。

hello.pl
&hello('アラシダ', 26);

subhello {
    my ($name, $age) = @_;

    print "僕の名前は$nameです\n"; # 僕の名前はアラシダです
    print "年齢は$age歳です\n"; # 年齢は26歳です
}

@_の中に引数が入ってきます。
取得した引数をそれぞれ変数へ入れて使用する形になります。

もちろん、returnで値を返却することもできます。

hello.pl
my $total = &sum(1, 3);
print "$total\n";

subsum {
    my ($num1, $num2) = @_;

    return $num1 + $num2;
}

# 実行結果
4

 

 

 

ファイル操作

説明
< filenameファイル読み込み
> filenameファイル書き込み(新規・上書き)
>> filenameファイル書き込み(追加)

もっとあるのですが、ひとまずこれさえ覚えていればいいかな、と思ってます。

hello.pl
# ファイル新規・書き込み

my $fh;
my $file_name = 'fruit.txt';
my $fruit = 'apple';

open $fh, "> $file_name";

print $fh $fruit;

close $fh;
hello.pl
# ファイル追加書き込み

my $fh;
my $file_name = 'fruit.txt';
my $fruit = 'banana';

open $fh, ">> $file_name";

print $fh $fruit,"\n";

close $fh;
hello.pl
# ファイル読みこみ

my $fh;
my $file_name = 'fruit.txt';

open $fh, "< $file_name";

while (my $line = <$fh>) {
    print $line;
}

close $fh;

 

 

 

正規表現

正規表現に関しては、PHPとさほど変わらないですね。

簡単に書き方だけ書いていきます。

fruit.pl
# パターンマッチ
my $fruit = 'apple';

if ($fruit =~ /a/) {
    print "aが含まれています\n";
} else {
    print "aが含まれていません\n";
}

# 実行結果
# aが含まれています

置換

正規表現を用いた置換を簡単に見ていきます。

置換したい文字列 =~ s/正規表現/置換後の文字列/;

fruit.pl
my $word = '私はappleが好きです';

$word =~ s/apple/banana/;

print "$word\n"; # 私はbananaが好きです

# 改行を削除
my $text = "改行を削除します\n";
$text =~ s/\n//;

print $text; # 改行を削除します

 

 

 

関数

Perlで用意されている関数を少しだけ見ていきます。

関数説明
chomp行末の改行を削除
map配列やハッシュを評価して結果を返す
grep条件を満たすものを取得
split文字列を分割する
join文字列を連結する
test.pl
# chomp
my $text = "行末の改行を削除します\n";
chomp($text);
print "$text\n"; # 行末の改行を削除します

# map
my @num1 = (1, 2, 3);
# $_ に1つ1つの要素が入ってくる
my @num2 = map {$_ * 2} @num1;

print "@num2\n"; # 2 4 6

# grep
my @fruit1 = ('apple', 'banana', 'melon');
my @fruit2 = grep {/a/} @fruit1;

print "@fruit2\n"; # apple banana

# split
my $word1 = "アップル,バナナ,メロン";
my @word2 = split(/,/, $word1);

print "@word2\n"; # アップル バナナ メロン

# join
my $word3 = join(',', @word2);

print "$word3\n"; # アップル,バナナ,メロン

 

 

 

終わりに

後半とても雑になった感じ満載です!
基本的にこの辺りを押さえとけばいいかなーと思ってます。

Perlを触る機会はあまりないかもしれませんが、触ってみると結構便利だなーと思いました。
このフォーマットでデータ欲しい、と思ってPerlで書いて一人で満足した思い出があります。笑

これをきっかけに少しでもPerlへの理解が深まればいいなと思います!!!

参考

perldoc.jp
このサイトはPerlの公式ドキュメント、モジュールのドキュメントを日本語に翻訳したものを表示するサイトです。
とほほのperl入門 - とほほのWWW入門
Perl基礎入門 | KentWeb
Perlによる基礎入門ページです。初心者向けに分かりやすく解説します。
Perlゼミ|Perlの基礎をインストールからサンプルで丁寧に解説
Perlゼミでは、Perlのインストールからはじめて、Perlプログラミングの基礎を学べる初心者向けの無料Web講座です。Perlの変数、配列、ハッシュ、if文、for文などの基本文法、ファイル入出力、日本語対応の検索・置換などの正規表現を使ったテキスト処理を学習できます。
Perl入門
プログラミング言語として Perl を使った方法を学習される方を対象として、 Perl によるプログラム記述方法について解説します。 Perl のプログラミングとしては CGI として Web サーバと連携した利用方法がよく使われますが、まず単独で動作するプログラムの作成を通して Perl の文法などについて学習してい...
Perlぜひ覚えておきたいテクニック - Perlゼミ|Perlの基礎をインストールからサンプルで丁寧に解説
Perlで開発するときに、ぜひとも覚えてほしいテクニックをまとめました。
【2016年度版】このPerlハマりどころがすごい!100連発 - Hatena Developer Blog
はじめに autovivificationを避ける myと後置ifを同時に使ってはならない return;で返る値は空のリスト 正規表現によるバリデーションでは\Aと\zを使おう '0' は偽で評価される each は中断した時、中断した時点の状態が残り続ける おわりに はじめに こんにちは。アプリケーションエンジニア...
PHP/Javascript/WORDPRESS案件全般承ります

この記事についてのご質問またはお困りのことがございましたら、お気軽にお問い合わせください。

タイトルとURLをコピーしました