Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Perl入学式

Perl入学式 #5

http://www.perl-entrance.org

Perl入学式について

会場について

ロゴについて

Perl入学式

IT勉強会スタンプラリー

IT勉強会スタンプラリー

喋ってる人

本日の内容

お約束

#!/usr/bin/env perl
use utf8;
use strict;
use warnings;

binmode STDIN,  ":encoding(UTF-8)"; # 標準入力
binmode STDOUT, ":utf8";            # 標準出力
binmode STDERR, ":utf8";            # 標準エラー出力

http://blog.nishimiyahara.net/2012/04/perl.html

前回までのおさらい

Q.画面に文字を出力する

制限時間 : 15秒

Hello World[改行]

A.画面に文字を出力する

#!/usr/bin/env perl
use utf8;
use strict;
use warnings;

binmode STDIN,  ":encoding(UTF-8)";
binmode STDOUT, ":utf8";
binmode STDERR, ":utf8";

print "Hello World\n";

Q.画面に日本語を出力する

制限時間 : 15秒

ハローワールド[改行]

A.画面に日本語を出力する

#!/usr/bin/env perl
use utf8;
use strict;
use warnings;

binmode STDIN,  ":encoding(UTF-8)";
binmode STDOUT, ":utf8";
binmode STDERR, ":utf8";

print "ハローワールド\n";

Q.画面から入力する

制限時間 : 15秒

A.画面から入力する

この解答例以降、お約束は省略します。

print "値を入力してください>>>";
my $input = <STDIN>;
chomp($input);
print "入力は $input です\n";

Q.四則演算

制限時間 : 15秒

A.四則演算

print "値1を入力してください>>>";
chomp(my $input1 = <STDIN>);
print "値2を入力してください>>>";
chomp(my $input2 = <STDIN>);
print "$input1 + $input2 = ", $input1 + $input2, "\n";
print "$input1 - $input2 = ", $input1 - $input2, "\n";
print "$input1 * $input2 = ", $input1 * $input2, "\n";
print "$input1 / $input2 = ", $input1 / $input2, "\n";

Q.条件分岐(数値比較)

制限時間 : 15秒

A.条件分岐(数値比較)

print "値1を入力してください>>>";
chomp(my $input1 = <STDIN>);
print "値2を入力してください>>>";
chomp(my $input2 = <STDIN>);
if ($input1 == $input2) {
  print "$input1 と $input2 は数値として等しい。\n";
}
else {
  print "$input1 と $input2 は数値として等しくない。\n";
}

数値として比較(関係演算子一覧)

my $x = 123;
my $y = 123;
if ( $x == $y ) { print "$x と $y は同じ\n";    }
if ( $x != $y ) { print "$x と $y は違う\n";    }
if ( $x >  $y ) { print "$x は $y より大きい\n"; }
if ( $x <  $y ) { print "$x は $y より小さい\n"; }
if ( $x >= $y ) { print "$x は $y 以上\n";      }
if ( $x <= $y ) { print "$x は $y 以下\n";      }

数値として比較(特殊)

my $result = $x <=> $y;  # $x <=> $y の結果を代入
if ( $result == 0 ) {    # 条件1
  print "$x と $y は同じ\n";
}
elsif ( $result < 0 ) {  # 条件2
  print "$x は $y より小さい\n";
}
else {                   # すべての条件に当てはまらない
  print "$x は $y より大きい\n";
}

Q.条件分岐(文字列比較)

制限時間 : 15秒

A.条件分岐(文字列比較)

print "値1を入力してください>>>";
chomp(my $input1 = <STDIN>);
print "値2を入力してください>>>";
chomp(my $input2 = <STDIN>);
if ($input1 eq $input2) {
  print "$input1 と $input2 は文字列として等しい。\n";
}
else {
  print "$input1 と $input2 は文字列として等しくない。\n";
}

文字列として比較(関係演算子一覧)

my $x = 'xyz';
my $y = 'xyz';
if ( $x eq $y ) { print "$x と $y は同じ\n";    }
if ( $x ne $y ) { print "$x と $y は違う\n";    }
if ( $x gt $y ) { print "$x は $y より大きい\n"; }
if ( $x lt $y ) { print "$x は $y より小さい\n"; }
if ( $x ge $y ) { print "$x は $y 以上\n";      }
if ( $x le $y ) { print "$x は $y 以下\n";      }

文字列として比較(特殊)

my $result = $x cmp $y;   # $x cmp $y の結果を代入
if ( $result == 0 ) {     # 条件1
  print "$x と $y は同じ\n";
}
elsif ( $result < 0 ) {   # 条件2
  print "$x は $y より小さい\n";
}
else {                    # すべての条件に当てはまらない
  print "$x は $y より大きい\n";
}

Q.条件分岐(上級)

制限時間 : 15秒

A.条件分岐(上級)

print "値1を入力してください>>>";
chomp(my $input1 = <STDIN>);
print "値2を入力してください>>>";
chomp(my $input2 = <STDIN>);
if ($input1 == $input2 && $input1 eq $input2) {
  print "$input1 と $input2 は数値として等しく、かつ、文字列として等しい。\n";
}
else {
  print "$input1 と $input2 は数値として等しくないか、文字列として等しくない。\n";
}

論理演算子一覧

my $x = 1;
my $y = 2;
if ( $x == 1 && $y == 2 ) {
  print "$x は 1 かつ $y は 2 です\n";
}
if ( $x == 2 || $y == 2 ) {
  print "$x は 2 または $y は 2 です\n";
}
if ( ! $y == 1 ) {
  print "$y は 1 ではありません\n";
}

Q.配列

制限時間 : 15秒

A.配列

my @array = ("最初", "真ん中", "最後");
print "$array[0]\n";
print "$array[-1]\n";

配列の操作(No.1/2)

my @empty_array = (); # 空の配列
my @defined_only;     # 宣言のみ
my @array = ('a', 'b', 'c');
push(@array, '最後');      # 最後の要素に加える
unshift(@array, '最初');   # 最初の要素に加える
print "@array\n";         # 最初 a b c 最後[改行]
my $pop   = pop(@array);  # 最後の要素を取り出す
my $shift = shift(@array); # 最初の要素を取り出す
print "@array\n";         # a b c[改行]
print "$pop\n";           # 最後[改行]
print "$shift\n";         # 最初[改行]

配列の操作(No.2/2)

my @array = ('a', 'b', 'c');
my @array2 = reverse(@array);  # 要素を逆並びにする
print "@array2\n";             # c b a[改行]
my @array3 = sort(@array2);    # 要素を順序良く並べる
print "@array3\n";             # a b c[改行]
my $str = join(":", @array);   # 要素を連結する
print "$str\n";                # a:b:c[改行]
my @array4 = split(/:/, $str); # 文字列を分割する
print "@array4\n";             # a b c[改行]

Q.ハッシュ(連想配列)

制限時間 : 15秒

A.ハッシュ(連想配列)

my %hash = (
  key1 => "value1",
  key2 => "値2",
);
print "$hash{key1}\n";
print "$hash{key2}\n";

Q.繰り返し(for文)

制限時間 : 15秒

1から10までの数値を持つ配列を作成し、すべての値を合計して表示するプログラムを(脳内で)作成してください。

A.繰り返し(for文)

my @array = (1 .. 10);
my $sum = 0;
for my $item (@array) {
  $sum += $item;
}
print "1から10の合計は${sum}です。\n";

Q.繰り返し(ループ制御)

制限時間 : 15秒

A.繰り返し(ループ制御)

my @array = (1 .. 10);
my $sum = 0;
for my $item (@array) {
  if ($item == 5) {
    next;
  }
  $sum += $item;
}
print "1から4と6から10の合計は${sum}です。\n";

Q.繰り返し(while文)

制限時間 : 15秒

A.繰り返し(while文)

my @array;
while (@array < 5) {
  print "文字列を入力してください>>>";
  chomp(my $input = <STDIN>);
  if ( $input ne "" ) {
    push @array, $input;
  }
  else {
    print "ちゃんと文字列を入力してください。\n";
  }
}
print "入力されたのは@{array}です。\n";

Q.パターンマッチ

制限時間 : 15秒

A.パターンマッチ

print qq{"y"を含んだ文字列を入力してください>>>};
chomp(my $input = <STDIN>);
if ($input =~ /y/) {
  print qq{${input}には"y"が含まれています。\n};
}
else {
  print qq{${input}には"y"が含まれていません。\n};
}

パターンマッチ(正規表現)

my $str = 'Yes';
if ( $str =~ /[yY]/ ) { # [...]の中身のいずれか1文字にマッチ
  print "$str には「y」または「Y」が含まれています\n";
}
if ( $str =~ /y/i ) { # iオプションは大文字小文字を無視してマッチ
  print "$str には「y」または「Y」が含まれています\n";
}

Q.リファレンス

制限時間 : 15秒

A.リファレンス

use Data::Dumper::Concise;
my %hash1 = (
  key1 => "value1",
  key2 => "value2",
);
my %hash2 = (
  key1 => "値一",
  key2 => "値二",
);
my @array = ( \%hash1, \%hash2 );
print Dumper \@array;

様々なリファレンス

my $scalar = 'string';
my @array  = ('a', 'b', 'c');
my %hash   = (key1 => 'value1', key2 => 'value2');
my $scalar_ref = \$scalar; # スカラーのリファレンス
my $array_ref  = \@array;  # 配列のリファレンス
my $hash_ref   = \%hash;   # ハッシュのリファレンス
my $scalar_ref_direct = \'Perl';
my $array_ref_direct  = +['d', 'e', 'f'];
                        # 「+」は省略可能
my $hash_ref_direct   = +{ key => 'value' };
                        # 「+」は省略可能

Q.デリファレンス

制限時間 : 15秒

リファレンスの定義

my $ref = {
  key1 => ["perl", "python", "php"],
  key2 => ["ruby"],
}

A.デリファレンス

my $ref = {
  key1 => ["perl", "python", "php"],
  key2 => ["ruby"],
};
print $ref->{key1}->[0], "\n";
print $ref->{key1}[0],   "\n";
print ${$ref}{key1}[0],  "\n";

様々なデリファレンス(配列)

my @array     = ('a', 'b', 'c');
my $array_ref = \@array;        # 配列のリファレンス
print join("\n", @{$array_ref}); # 配列全体をデリファレンス
print "\n";
print "$array_ref->[0]\n";  # 配列のリファレンスの最初の要素
print "$array_ref->[1]\n";  # 配列のリファレンスの2つめの要素
print "$array_ref->[-1]\n"; # 配列のリファレンスの最後の要素

様々なデリファレンス(ハッシュ)

my %hash = ( key1 => 'value1', key2 => 'value2' );
my $hash_ref = \%hash;
    # ハッシュのリファレンスを作成
for my $key ( keys %{$hash_ref} ) {
    # ハッシュ全体をデリファレンス
  print "$key : $hash_ref->{$key}\n";
    # ハッシュの要素を表示する
}

変数(スカラー変数)のおさらい

my $str = 'これは文字列です';
my $num = 123;
print "文字列( $str )と数値( $num )\n";

配列の使い方のおさらい

my @array = ('a', 'b', 'c');
print "$array[0]\n";
print "@{array}\n";
for my $item ( @array ) {
  print "$item\n";
}

配列のリファレンス

my $array_ref = +['a', 'b', 'c']; # 「+」は省略可能
print "$array_ref->[0]\n";
print "@{$array_ref}\n";
for my $item ( @{$array_ref} ) {
  print "$item\n";
}

ハッシュの使い方のおさらい

my %hash  = (
  key1 => 'value1',
  key2 => 'value2',
);
print "key1 : $hash{key1}\n";
for my $key ( keys %hash ) {
  print "$key : $hash{$key}\n";
}

ハッシュのリファレンス

my $hash_ref  = +{ # 「+」は省略可能
  key1 => 'value1',
  key2 => 'value2',
};
print "key1 : $hash_ref->{key1}\n";
for my $key ( keys %{$hash_ref} ) {
  print "$key : $hash_ref->{$key}\n";
}

休憩(15分)

コマンドラインからPerlスクリプトを使おう

#!(シバン)とは

シバンまたはシェバン (shebang) とはUNIXのスクリプトの#!から始まる1行目のこと。起動してスクリプトを読み込むインタプリタを指定する。 hash-bangまたはsharp-bangとも言うが、後者を縮めたshebangという呼び方が一般的かつシンプルである。

#!(シバン)を書かなかった場合

$ perl scriptname.pl

#!(シバン)を書いた場合

$ chmod +x scriptname.pl # 実行権限を与える
$ ./scriptname.pl        # スクリプトファイルがコマンドのように使る

@ARGV(アットマーク・アーグヴィ)

scriptname.plの中身

my @opts = @ARGV;
print "@opts\n";

実行する時に引数を与える

$ ./scriptname.pl a b c

コマンドラインの練習問題

制限時間 : 5分

ファイルを使おう

ファイルから読み込もう

my $fh;
open $fh, "<", "file1.txt"; # file1.txtを読み込みモードでオープン
my @lines = <$fh>;          # @linesにファイルの内容を代入
print @lines;               # 画面に出力する
close $fh;                  # ファイルを閉じる

ファイルに書き込もう

my $fh;
my @array = ("a", "b", "c");
open $fh, ">", "file2.txt";
for my $item (@array) {
  print $fh "$item\n";       # $fh に対して出力する
}
close $fh;

モード各種

ファイルの状態を確認しよう

-r(読み込み出来るかを確認)

my $filename = "404.txt";
if (-r $filename) {            # 404.txtが読み込み可能か確認
  open my $fh, "<", $filename; # 変数の宣言はopenと同時でも良い
  my @lines = <$fh>;
  print @lines;
  close $fh;
}
else {
  die qq{can not read "$filename"}; # ファイルが読み込みできないので異常終了
}

-w(書き込み出来るかを確認)

my @array = ("a", "b", "c");
my $filename = "404.txt";
if (-w $filename) {            # 404.txtが書き込み可能か確認
  open my $fh, ">", $filename; # 変数の宣言と同時でも良い
  for my $item (@array) {
    print $fh "$item\n";       # $fh に対して書き込み
  }
  close $fh;
}
else {
  die qq{can not write "$filename"}; # ファイルが書き込みできないので異常終了
}

ファイルの練習問題

制限時間 : 5分

外部コマンド(シェル)を使おう

exec

exec("ls");
print "OK\n"; # 実行されない

system

system("ls");
print "OK\n"; # 実行される

``(バッククォート)

my @results = `ls`;
print @results;

qx{}

my @results = qx{ls};
print @results;

外部コマンドの練習問題

制限時間 : 5分

関数(サブルーチン)を使おう

サブルーチンとは?

サブルーチン(英: subroutine)は、コンピュータプログラミングにおいて、プログラム中で意味や内容がまとまっている作業をひとつの手続きとしたものである。ソースコード上ではコードブロックを形作る。繰り返し利用されるルーチン作業をモジュールとしてまとめたもので、呼び出す側の「主」となるもの(メインルーチン)と対比して「サブルーチン」と呼ばれる。サブプログラム (subprogram) とも呼ぶ。

関数とは?

サブルーチンを、結果として値を返すものと処理だけを行い値を返さないものに分類することがある。その場合、前者を関数(かんすう)、後者を手続き(てつづき)と呼んで区別する。プログラミング言語の仕様としてCのようにどちらかの呼び方のみを採るものと、Pascal のように両者を区別するものがある。

Perlにおける関数

Perlでは「関数」は「サブルーチン」と同じです。

あえて区別するとすれば、値を返すサブルーチンを関数と呼んでもよいでしょう。

標準の関数を使ってみよう

my $sin90 = sin(3.14159 / 2);
print "$sin90\n";

関数を定義しよう

ラジアンの計算が面倒なので、度数法の角度を入力するとsinの値が返ってくる関数を定義します。

my $sin90 = &decsin(90);
print "$sin90\n";

sub decsin {
  my $dec = shift(@_);
  my $sin = sin( $dec / 180 * 3.14159 );
  return $sin;
}

関数を定義する方法

関数の使い所

cosについても同様に関数を定義します。

print &deccos(90), "\n"; # 直接printしてもOK

sub deccos {
  my $dec = shift(@_);
  my $cos = cos( $dec / 180 * 3.14159 );
  return $cos;
}

処理をまとめる

sub deccos {
  my $dec = shift(@_);
  my $cos = cos( &dec2rad($dec) );
  return $cos;
}

sub dec2rad {
  return $_[0] / 180 * 3.14159;
}

省略できる変数

@_(アットマーク・アンダーバー)

my $sin90 = &decsin(90);
print "$sin90\n";

sub decsin {
  my $dec = shift; # @_が対象になる
  my $sin = sin( $dec / 180 * 3.14159 );
  return $sin;
}

$_(ドルマーク・アンダーバー)

my @array = ("a", "b", "c");
for my $item (@array) {
  print "$item\n";
}

これは、以下のようにしても動きます。

my @array = ("a", "b", "c");
for (@array) {
  print "$_\n";
}

関数の練習問題

制限時間 : 5分

コンテキストを使いこなそう

コンテキストとは?

コンテキスト(Context)とは、直訳すると「文脈」という意味です。

Perlには2つの主要なコンテキストがあります。

特に代入しようとする場合、このコンテキストによって得られる値が変化する場合があります。

コンテキストを実感してみよう

my @local_time = localtime;
print "@local_time\n";

配列変数に代入しようとすると、localtimeはリストコンテキストとして動作します。

my $local_time = localtime;
print "$local_time\n";

スカラー変数に代入しようとすると、localtimeはスカラーコンテキストとして動作します。

リストコンテキスト

my @array = ("a", "b", "c"); # リストコンテキスト

my ($scalar1, $scalar2, $scalar3) = ("a", "b", "c"); # リストコンテキスト
print "$scalar1\n";
print "$scalar2\n";
print "$scalar3\n";

my ($scalar) = ("a", "b", "c"); # リストコンテキスト
print "$scalar\n";

スカラーコンテキスト

my @array = ("a", "b", "c"); # これはリストコンテキスト

my $scalar = @array; # スカラーコンテキスト
print "$scalar\n";

my $scalar2 = ("a", "b", "c"); # スカラーコンテキスト
print "$scalar2\n";

コンテキストをコントロールしよう

my @list_lt = localtime;
print "@list_lt\n";

my @scalar_lt = scalar(localtime);
print "@scalar_lt\n";

演習問題

問題

制限時間 : 10分

質問タイム

お疲れさまでした

Use a spacebar or arrow keys to navigate