Edited at

Perl入門・基本的な書き方

More than 3 years have passed since last update.


はじめに

PHPerのぼくが、Perlを触った思い出に基本的なことを書いていこうと思います。

というのも、毎回Google先生に聞くのもいいのですが無くなる記事も多くあるので

自分でまとめちゃおうという魂胆です(`・ω・´)ゞ

初心者のぼくでも少しだけ書けるようになったので基礎をかじる程度にはなれるのかなーと。


処理を書く前に

まず、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 == y
eq
x と y が等しいなら真

x != y
ne
x と y が等しくないなら真

x < y
lt
x が y より小さければ真

x > y
gt
x が yより大きければ真

x <= y
le
x が y 以下なら真

x >= y
ge
x が 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();

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

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


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


hello.pl

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

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

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


@_の中に引数が入ってきます。

取得した引数をそれぞれ変数へ入れて使用する形になります。

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


hello.pl

my $total = &sum(1, 3);

print "$total\n";

sub sum {
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への理解が深まればいいなと思います!!!