Perl学習-基礎文法編

がっつりPerlを書く機運が高まってきたので、基礎文法を殴り書きでメモすることにした。

＿人人人人人人人＿
＞　突然のPerl　＜
￣Y^Y^Y^Y^Y^Y￣


```perl

use strict;
use warnings;

#[1] 変数 データ(スカラー値、配列、ハッシュ)

## (1)スカラー(単一の値: 数値、文字列) 変数 : $
my $msg = "hello world\n";
print $msg;


my $x =  10;
my $y =  10.7;
my $z =  123_456_789;


## (2)配列変数 : @
my @sales = (150, 200, 300);

#　同じ意味です
my @colors = ('red', 'green');
my @colors2 = qw(red green); #クローテッドワード

# 1から100まで
my @inc  = (1..100); 

# 配列で添字指定で単一の値を取得する時はスカラー値(=単一)になるので、@ではなく$の記述にします(重要)

print $sales[1] # 200
print $sales[-1] # 300

# 複数の値を取得する時は@の記述をします。
print @sales[0..1] # 150 200

# 特殊な記述の末尾の添字が取得できます
print $#sales # 末尾の添字 ここでは2が表示されます

# こんな感じに応用できます
print @sales[1..$#sales] # 200 300


## (3)ハッシュ変数 : キーと値 : %

my %sales_map = ("tanaka" => 300, "suzuki" => 150,"ohira" => 200);

# こちらも取り出す値は単一なので%ではなく$にします
print $sales_map{"tanaka"};

#[2] 条件分岐

my $score = 50;

## 数値
if ($score >= 80) {
	print "OK\n";
} elsif ($score >= 40){
	print "uuuum\n";
} else {
	print "not ok....\n";
}

## 文字列:
my $name = "luke";

if ($name eq "luke") {
	#print "i am luke";
}

## 文字列の比較演算子 eq ne gt lt ge le : 0-9 < A-z a-z

## 論理演算子 && || !

## 後置if perlもできるのか
print ("ok") if ($score >= 30);

## 三項演算子

my $a = 10;
my $b = 20;

my $max = ($a > $b) ? $a : $b;

print $max;

#[3] ループ

## (while)
my $i = 0;

while($i < 10){
	print "i = $i\n";
	$i++;
}

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

## (foreach)
my @colors3 = qw(red green orange pink);

# 以下の3つは同じ挙動になります(記述の省略版)
foreach my $color (@colors3) {
	print "color = $color\n";
}

for my $color (@colors3) {
	print "color = $color\n";
}

for (@colors3) {
	# 特殊変数の $_に1つづつ入る(perlっぽい)
	print "color = $_\n";
}


#[4] ハッシュループ
my %sales_map2 = ("tanaka" => 300, "suzuki" => 150,"ohira" => 200);

# 以下の2つのループは同じ挙動になります(記述の省略版)

# ちなみに順不同(Pythonでいうdictな感じ)
foreach my $key (keys(%sales_map2)){
	print "sales for $key is $sales_map2{$key}\n";
}

# 特殊変数の $_ には 添字がはいります
for (keys %sales_map2) {
	print "sales for $_ is $sales_map2{$_}\n";
}


#[5] ファイルの入出力

## ファイルの読み込み
open(my $in, "<", "test.dat") or die("could not open file");

## ファイルの書き込み(test.outって空ファイルを作成するよ!)
open(my $out, ">", "test.out") or die("could not open file");

while (<$in>) { # 一行づつ読み込むんやで
	print $_; 
	print $out $_; # test.outファイルに書き込みます
}

close($in);
close($out);


#[5] 正規表現
open(my $in2, "<", "test.dat") or die("could not open file");
while (<$in2>) { # 一行づつ読み込むんやで
	$_ =~ s/abc/ABC/;
	if ($_ =~ /[a-z]/) {
		print $_; # 小文字だけ出力されます
	}
	print $_;
}

## それをさらに省略だ!( perlは特殊変数に関する処理は省略できます!...まじかよ...)
open(my $in3, "<", "test.dat") or die("could not open file");
while (<$in3>) { # 一行づつ読み込むんやで
	s/abc/ABC/;
	if (/[a-z]/) {
		print $_; # 小文字だけ出力されます
	}	
}


#[6] サブルーチン

sub max {
	my $max = $_[0]; # 2
	if ($_[1] > $max) {
		$max = $_[1];
	}
	#return $max;
	$max; # returnを書かなくても最後の変数をreturnしてくれる(rubyっぽい)
}

print max(2, 8);


#[7] サブルーチン2

## さぁ省略した記述だよ!
sub max2 {
	# @_は引き数のリストです(特殊変数)なので、@_ は (12, 8, 100, 23, 38)です
	# shiftはリストの先頭を抜き出す
	my @max = shift(@_); # max = 12
	foreach (@_) {
		$max = $_ if $_ > $max;
	}
	$max;

}

print max2(12, 8, 100, 23, 38);



#[8] eval関数
# 引き数が指定されていないと、evalは$_の内容を実行します。
# 公文エラーが発生すると、特殊変数$@にエラーがはいります。
# エラーが発生しなければ、$@は空のままです。
# eval()をしない場合は、scriptの処置はそこで止まってしまうが、eval()をする事で処理が止まらなくなります。
# eval関数に評価対象の命令を文字列として指定しています。
# 変数名の＄に\をつけてエスケープシーケンスしているkと尾に注意してください!


eval("\$value = 2 / 0");
#print "エラーが発生しました: $@" if($@);

# print の実行結果
# エラーが発生しました: Global symbol "$value" requires explicit package name (did you forget to declare "my $value"?) at (eval 1) line 1.


#[9] グローバル変数とローカル変数
# localで宣言した変数の値は、別のサブルーチンから参照できる。
# myで宣言した変数の値は山陽できない
# localで宣言した変数の値は別のサブルーチンで変更可能

# $hoge = "hoge"; # グローバル変数
# my $fuga = "fuga"; # myで宣言したlocal変数
# local $piyo = "piyo"; # localで宣言したlocal変数


#[10] リファレンス
## Perlにはリファレンスという機能が用意されています。リファレンスはC言語のポインタに相当します。
# スカラー変数をリファレンスで渡し、サブルーチンで内容を変更しています。

my $string = "私はは太郎です";
print "実行前: $string\n";
sub_reference(\$string);
print "実行後: $string\n";

sub sub_reference {
	# リファレンスを受ける
	my ($reference) = @_;

	# リファレンスのスカラー変数の内容を変更
	$$reference =~ s/太郎/花子/;
}

## 実行結果
# 実行前: 私はは太郎です
# 実行後: 私はは花子です


#[11] ライブラリファイル
# スクリプトの最後に　1; (「真」の意味)をつけます。

#[12] モジュール
# モジュールを呼び出すには、useステートメントをを使います

#[13] tips

## 配列にhash
## see : http://d.hatena.ne.jp/perlcodesample/20100930/1278596435

my $persons = [
	{name => "sakura", weight => 69},
	{name => "negi", weight => 16}
	];

foreach my $hash (@$persons) {	
	warn Dumper $hash->{name};
}

## 多次元ハッシュ
## see : http://www.kent-web.com/perl/chap4.html

my %hash = (
	A => { name => "hoge", foot => 27, weight => 68},
	B => { name => "fuga", foot => 30, weight => 200},
);

foreach my $h (keys %hash) {
	warn Dumper $hash{$h};
}
```