- 前回の復習
- おまじない
- 変数
- 標準入力
- 四則演算
- 基本的な演算子
- if, else文
- 論理演算子
- for文, 配列
print "Hello, World!\n";
- このように書いたものを,
hello.pl
として保存します print
は, 端末に文字を出力します\n
は改行を表します- 最後に
;
を忘れずに!
$ perl hello.pl
Hello, World!
perl
の引数に実行するスクリプトファイル名を与えると, そのスクリプトを実行します
#!/usr/bin/env perl
use strict;
use warnings;
- おまじないとして, 冒頭の3行を書くようにしよう
use strict
-> 厳密な書式を定めたり, 未定義の変数を警告するといった効果がありますuse warnings
-> 望ましくない記述を警告してくれる効果があります- 以下, この資料のサンプルコードではこれを「お約束」として省略します
- 書かれているものとして扱ってください
Hello, Perl Entrance!
という文字列を出力するhello_perl.pl
を書いて下さい- わからない所があれば, 近くのサポーターに聞いて下さい!
- 「変数」は, いわば「データを格納できる箱」です
- Perlの変数には, 「スカラ変数」, 「配列」, 「連想配列(ハッシュ)」という3つの種類があります
- 「スカラ変数」は, 「1つの要素しか入らない箱」と思って下さい
- 「配列」と「連想配列(ハッシュ)」は, 「複数の要素を格納出来る箱」と思って下さい
- まずは, 1つの要素を格納できる「スカラ変数」について見て行きましょう
my $foo; # スカラ変数 $foo を宣言
$foo = 1; # $foo に整数 1 を代入
my $bar = 3.14; # $bar を宣言し実数 3.14 を代入
$bar = "baz"; # $bar に文字列 baz を代入
- スカラ変数の先頭には,
$foo
のように$
をつけます$
はスカラ(scalar)
のS
, と覚えるとよいでしょう
=
という記号(代入演算子)を使うことで, 左辺のスカラー変数に右辺の値を入れる(代入する)ことができます- 変数を宣言するとき(初めて使うとき)は, 先頭に
my
をつけます Perl
では, C言語やJavaのようにint
やchar
といった「型」がないので, 数値や文字列などを自由に代入することができます
my $foo;
my $bar = 3.14;
$bar = "baz";
- ところで, ここで出てきた変数名
foo, bar, baz
は, 意味のない「仮の名前」(メタ構文変数)です. このように, プログラミングで変数や関数に名前を付ける際, どのような名前でも良い場合には foo, bar, baz がよく使われます - 日本では hoge, piyo, fuga なども使われますが, 特別の理由がなければ foo, bar, baz で良いでしょう
my $foo = 1;
print "$foo\n"; # 「1」が出力される
print '$foo\n'; # 「$foo\n」が出力される
print
を使うことで変数を出力することができます- 変数を出力する場合は,
""(ダブルクォテーション)
の中に変数を書きましょう""
の中に変数を書くと, その変数の中身が展開されて表示されます''
の中では, 展開はされず, 全てがそのまま出力されます- 変数だけでなく,
\n
などもそのまま出力されます!
- 変数だけでなく,
\n
は改行を意味します
my $foo = 1;
print "$foo\n"; # 「1」が出力される
print '$foo\n'; # 「$foo\n」が出力される
- Perlでは,
#
より後ろの文字列は全てコメントとして扱われます- コメントは, 実行されません
- この資料の中で, コメントを使ってコードに補足を行うことがあります
- 自分の名前, 年齢, 身長などの情報をそれぞれ
name
,age
,height
といったスカラ変数に格納し, それらの値を出力するスクリプトprofile.pl
を作成しよう - 「お約束」の3行を忘れずに!
- 標準入力(Standard Input)とは、プログラムに入ってくるデータです
- 通常, キーボードから入力されるテキストデータのことを指します
Perl
では, この「標準入力」をプログラムの中で<STDIN>
と表現します
my $str = <STDIN>;
chomp $str;
print $str;
- 端末からPerlに対して, 標準入力を使って文字列を入力することができます
- 1行目では,
<STDIN>
で端末から入力された文字列を受け取り, 受け取った文字列を変数str
に代入しています - 2行目では,
chomp
で行末の改行を削除しています<STDIN>
で端末から受け取ったデータには改行が含まれているためです
- 1行目では,
print 'input > ';
my $str = <STDIN>;
chomp $str;
print "$str\n";
- このコードを動かしてみます
<STDIN>
がどのような働きをするか見てみましょう
my $foo = 4;
my $bar = 2;
my $result;
$result = $foo + $bar; # 4 + 2 = 6
$result = $foo - $bar; # 4 - 2 = 2
$result = $foo * $bar; # 4 * 2 = 8
$result = $foo / $bar; # 4 / 2 = 2
$result = $foo % $bar; # 4 % 2 = 0
$result = $foo ** $bar; # 4の2乗は 16
Perl
はC言語と異なり, べき乗の計算を簡単に行うことができます
my $foo = 4;
$foo = $foo * 3; # 4 * 3 = 12
- 代入演算子
=
は, 算数のイコールとは性質が異なります - 上記の例では右辺の「4 * 3 = 12」が
=
の左辺へ代入され, 左辺の$foo
が「12」になります
my $foo = 4;
my $bar = 2;
$foo = $foo + 1;
$foo += 1;
++$foo; # または $foo++
# すべて「4 + 1 = 5」
$bar = $bar - 1;
$bar -= $bar;
--$bar; # または $bar--
# すべて「2 - 1 = 1」
- 「1」ずつ加減したい場合は上記のように記述できます
- 「1」ずつ加算することを「インクリメント」, 減算することを「デクリメント」といいます
my $foo = 'hoge';
my $bar = 123;
my $baz = $foo . $bar; #=> hoge123
print $foo . $baz . "\n"; #=> hogehoge123
.
で, 文字列や変数を連結することができます
my $foo = 2 + 4 * 3; #=> 14
my $bar = (2 + 4) * 3; #=> 18
- 演算の順序は,
()
を付けることで変更することができます- 通常の数学と同じく, Perlも足し算・引き算より掛け算・割り算の優先順位が高いです
- しかし, 2行目では
()
を付けることで足し算を先に計算させています
1 + 2 = 3
1 - 2 = -1
1 * 2 = 2
1 / 2 = 0.5
- 標準入力
<STDIN>
から0以外の整数を2つ読み込み, それらを四則演算(+
,-
,*
,/
)した結果を上の例のように出力するスクリプトcalc.pl
を作成しよう
my $foo = 1;
if ( $foo == 1 ) {
print "OK\n"; # 条件が「真」の場合
} else {
print "NG\n"; # 条件が「偽」の場合
}
==
は"右辺と左辺が数値として等しければ真"であることを意味します- 真 = 条件が正しい / 偽 = 条件が正しくない
- ここでは
$foo
が1
と等しい場合に真となり,OK
という文字が表示されます $foo
が1
でなければ, 偽となるためelse
に処理が移りNG
という文字が表示されます
my $foo == 1; # まちがい
my $bar = 1; # せいかい
- 代入の
=
と, 数値の比較の==
をよく間違えます- この場合, 実行すると
Use of uninitialized value $foo in numeric eq (==)
のようなエラーになります
- この場合, 実行すると
my $foo = 1;
if ($foo = 2) { ... } # まちがい
if ($foo == 2) { ... } # せいかい
- 数値の比較の
==
と, 代入の=
をよく間違えます- この場合, 実行すると
Found = in conditional, should be ==
のような警告が出ます
- この場合, 実行すると
my $foo = 1;
if ( $foo == 1 ) {
print "OK\n"; # 条件が「真」なので出力される
}
else
の部分は省略することもできます- この状況で条件が「偽」の場合(
$foo
が1
ではない場合), 何の処理も行われません
- この状況で条件が「偽」の場合(
== # 右辺と左辺が等しいならば真
!= # 右辺と左辺が等しくないならば真
< # 右辺より左辺が小さいならば真
> # 右辺より左辺が大きいならば真
<= # 右辺が左辺以上ならば真
>= # 右辺が左辺以下ならば真
- 数字同士を比較するときは, このような比較演算子を使います
eq == equal
ne != not equal
gt > greater than
ge >= greater equal
lt < less than
le <= less equal
- 数値を比較する場合は
==
や!=
を使いますが, 文字列を比較する場合はeq
やne
といった演算子を使います- もっとも,
eq
,ne
以外はあまり使いません - 「文字列の大小」とは, 辞書順に並べた時に前にくるものが小さく, 後ろにくるものが大きいという意味です
- もっとも,
my $foo = 'hello';
if ( $foo eq 'hello' ) {
print "OK\n";
} else {
print "NG\n";
}
- 今回は文字列を比較しているので,
==
ではなくeq
を用いています
if ('42strings' == 42) {
print "OK\n";
}
use warnings
が有効であれば, 文字列を数値用の比較演算子で比較しようとすると, 次のような警告を出力しますArgument "42strings" isn't numeric in numeric eq (==)
- このような場合, Perlは文字列を無理やり数値として解釈して処理を継続します
- この場合, '42strings'には先頭に
42
という数値が含まれているので, Perlは==
の演算子の左辺は42
として処理を実行します - そのため, この比較は真となり, 「OK」という文字列が出力されます
- この場合, '42strings'には先頭に
if ('42' eq 42) {
print "OK\n";
}
- 逆に, 文字列の比較演算子で数値を比較しようとした場合, 警告は出力されません
- Perlは自動的に数値を文字列として解釈して,
eq
演算子の右辺は'42'
として扱われます - そのため, この比較は「真」となり, 「OK」という文字列が出力されます
- Perlは自動的に数値を文字列として解釈して,
- Perlには,
true
やfalse
などで真偽値を表すことはできません - そのかわりPerlでは, 次の5つの値が「偽」の値(偽値)として扱われます
- 数値「
0
」 - 文字列「
'0'
」と「''
」 - 空のリスト「
()
」 undef
- 数値「
- そしてこれ以外の値は, Perlでは全て「真」として扱われます
my $foo = 1;
if ( $foo == 1 ) {
...
} elsif ( $foo == 2 ) {
...
} elsif ( $foo == 3 ) {
...
} else {
...
}
elsif
を使うことで, 分岐条件をさらに増やすことができます- PerlにはC言語の
switch
にあたるものはないので,if
,elsif
,else
で代用しましょう
- PerlにはC言語の
#!/usr/bin/env perl
use strict;
use warnings;
my $answer = 'perl'; # 好きな文字を入力しておく
- 簡単な文字当てゲーム
question_word.pl
を作成しよう - 端末から, 標準入力で文字列を一つ入力し, その文字列が
$answer
と一致したらOK
, 外れたらNG
と表示します
&& -> かつ
|| -> または
if文
で複雑な条件を扱いたいときは,関係演算子
を用いて複数の条件を連結しましょう&&
演算子は「かつ」なので, 両方の条件が真となるときのみ真となります||
演算子は「または」なので, 条件のどちらか1つでも真となるならば真となります
my $foo = 64;
if ( $foo > 0 && $foo % 2 == 0 ) {
print "&&: OK\n";
}
if ( $foo > 0 || $foo % 2 == 1 ) {
print "||: OK\n";
}
- 2行目は, 「64は0より大きい(真)」かつ「64を2で割った余りは0(真)」なので, 真となります
- 5行目は, 「64は0より大きい(真)」または「64を2で割った余りは1(偽)」なので, 真となります
#!/usr/bin/env perl
use strict;
use warnings;
my $answer = 1; # 好きな値を入力しておく
- 簡単な数当てゲーム
question_num.pl
を作成しよう - 端末から数字を一つ入力し, その数字が
$answer
と一致したらOK
,$answer
より大きければtoo big
, 小さければtoo small
と表示します- オプション: 入力した値が,
$answer
から-5〜+5の範囲内(例えば,$answer
が10なら, 5〜15)の場合,near
と表示するようにしてみましょう(時間に余裕があれば, チャレンジしてみてください!)
- オプション: 入力した値が,
my @array = ( 1, "foo", 3 );
print "@array\n"; #=> 1 foo 3
- 配列を使うことで, 数値や文字列をまとめて格納できます
=
演算子を使うことで, 左辺の配列に右辺の値を代入することができます- 配列は変数名の前に
@
をつけます@
はアレイ(array)
のa
, と覚えるとよいでしょう
- 1行目の右側,
( ... )
の部分をリストと呼びます
my @array = ( 1, "foo", 3 );
print "$array[0]\n"; #=> 1
print "$array[1]\n"; #=> foo
print "$array[2]\n"; #=> 3
- 配列の一つ一つの要素にアクセスする場合は
$変数名[添字]
を使います- 添字は1ではなく0からスタートして, 1ずつ増えます
my @array = ( 1, "foo", 3 );
print "$array[0]\n"; #=> 1
- 配列に格納された, ある要素を取得する方法が
@変数名[添字]
ではなく$変数名[添字]
となっているのは, 「配列に格納された1つの要素」がスカラ(1つ)のデータであるためです
my @array = ( 1, "foo", 3 );
$array[0] = "bar"; #=> ( "bar", "foo", 3 )
- 配列に新たな要素を代入する際は, 取り出すときと同様に添字を使います
my @array = ( 1, "foo", 3 );
my $sum = $array[0] + $array[2];
print "$sum\n" #=> 4
- 配列の要素は普通のスカラ変数と同じように扱えるので, このような計算もできます
my @array = ( 1, "foo", 3 );
print scalar @array; #=> 3
print $#array; #=> 2
- 配列を
scalar
演算子に与えると, 配列に格納されている要素の個数を取得できます @array
に対して$#array
と書くことで, 配列に格納されている最後の要素の添字を取得できます
my @array1 = ( 1, 2 );
my @array2 = ( 1 .. 5 );
my @array3 = ( @array1, 3 ); #=> (1, 2, 3)
()
を使うことで, 配列にまとめて値を代入することができます- 連続する数字であれば, 範囲演算子
..
を使って1 .. 5
と書くことで,1以上5以下
の値を配列に代入できます- ただし, 必ず右側の値が左側の値より大きくなければなりません.
@array2 = ( 5 .. 1 );
のように書くと@array2
には空の要素が格納されるので注意しましょう
- ただし, 必ず右側の値が左側の値より大きくなければなりません.
- 3行目のように, 数値や文字列だけでなく, 配列を代入することもできます
my @array = ( 1, "foo", 3 );
for my $foo ( @array ) {
print "$foo\n";
}
- 配列の中身を出力する方法として,
for
文がありますforeach
と書いても問題ありません. 実はPerlの内部では, 同じように処理されます
- この場合, 変数
$foo
に$array[0]
,$array[1]
... という値が順番に代入され, 処理が行われます
- 配列
@array
に好きな数値や文字列を設定し、for文で出力してください。 <STDIN>
を用いて配列@array2
に好きな数値や文字列を入力し、for文で出力してください。
FizzBuzz
問題にチャレンジ!!- 1から100までの数字について, 以下のようなルールに従って表示を行う
fizzbuzz.pl
を作成しよう!- その数字が
3
で割り切れるならFizz
5
で割り切れるならBuzz
3
でも5
でも割り切れるならFizzBuzz
- その数字が
- 1から100までの数字について, 以下のようなルールに従って表示を行う
my @array = qw( Alice Bob Chris );
#=> ('Alice', 'Bob', 'Chris')
- これまでのリストの書き方
('this', 'is', 'list', 1, 2, 3)
と異なり、クォート記号が不要です。 - この記法では空白文字 (スペース、タブ、改行など) が無視され、残ったものがリストの要素になります。
-
なので、こういう書き方もできます。
my @arary = qw( Alice Bob );
qw! Alice Bob !
qw# Alice Bob #
qw/ Alice Bob /
デリミタ (区切り文字) には任意の記号文字を使えます。
これらは前述の
qw( Alice Bob )
と等しくなります。
このような問題に遭遇したとき、
qw/http://www.perl-entrance.org http://www.yahoo.com/
# エラーになってしまう!
# デリミタがスラッシュ (/) で
# 要素にもスラッシュが含まれているため
解決法は2つ。
# 1. 要素内のスラッシュをバックスラッシュでエスケープする
# => 読みにくく感じるかもしれない
qw/ http:\/\/www.perl-entrance.org http:\/\/www.yahoo.com /
# 2. デリミタを変える
# => ちょっと読みやすいかもしれない
qw! http://www.perl-entrance.org http://www.yahoo.com !
配列には便利な関数があります。「関数」とは、ある働きをもつ「機能」のことだと思ってください。ここではその一部を紹介します。
- split
- join
join は分割された文字列をくっつけて、1つの文字列にします。
my @words = qw( I Love Perl. ); # qwショートカット
my $poem = join '_', @words;
print $poem; # => 'I_Love_Perl.'
- join が受け取る第1引数 (上の例ではアンダースコア) は、リストの要素をくっつける糊のような役割を果たします。
- 第2引数には、対象の配列を渡します。
split は指定したパターンに従って文字列を分割します。
my $poem = 'I Love Perl.';
my @words = split / /, $poem; #=> ('I', 'Love', 'Perl.')
- 引数として与えた文字列を、 // でくくった文字 (上の例では半角スペース) で分割して配列に格納します。
- // は正規表現リテラルと呼ばれるものです。正規表現については次回以降に詳しく説明します。
- 次の処理をする
join.pl
を作りましょう。("0120", "123", "XXX")
という配列を作ってください。- 1の配列をjoin関数で連結してください。
電話番号っぽいので、ハイフン ('-') でくっつけてみましょう。
- 次の処理をする
split.pl
を作りましょう。- "There's more than one way to do it." という文字列を作り、split関数で" "(半角スペース)ごとに分割して配列
@array
に格納し、出力してください。 - 好きな文字列を作り、好きな要素で区切って配列
@array2
に格納し、出力してください。- 日本語や数字を混ぜてもよいでしょう。
- わからないところがあれば、サポーターに聞いてみましょう!
- "There's more than one way to do it." という文字列を作り、split関数で" "(半角スペース)ごとに分割して配列
- practice.md
- 今回の内容を復習することができる問題集です
- ご不明な点があれば, 気軽にスタッフまでお尋ねください
-
- 各会場の講師が書いた, 練習問題の解答例はこちらで公開しています
- ※講義終了後に随時追加していきます
-
- 昨年分の解答例はこちらで公開しています
- その他、本編で紹介しきれなかった内容を補足します。
-
本編でも説明したとおり,
$#array
は@array
の最後の添字を表します- この場合,
@array
には3個の要素が格納されているので,$#array
は2となります
- この場合,
-
この性質を応用して, 以下のように書くことができます
my @array = ( 1, "foo", 3 ); for my
$i (0 .. ($ #array)) { print "$array[$i]\n"; }
my @array = ( 1, "foo", 3 );
for ( my $i = 0; $i < scalar(@array); $i++ ) {
print "$array[$i]\n";
}
scalar(@array)
は,@array
の要素数を表します -この場合,@array
には3個の要素が格納されているので,scalar(@array)
は3となります- もっとも, よほどの事がないかぎり, この方式の
for
は使いません!- 先ほど紹介したforループで大抵事足りるためです