Perl言語 の一部を紹介します。
学校では、パソコンに既にインストールしてありましたが、自宅で個人的に勉強するときは、 検索エンジンで探して、条件や注意をよく読んで、同意できる場合、ダウンロードします。
シングルクォート ダブルクォート 表現したい文字列
'hello' "hello" hello
'Don\'t do it!' "Don't do it!" Don't do it!
'hello "hello hello(改行)
there' there" there
"hello\nthere" hello(改行)
there
$name="tokyo"; print "this is $name\n"; # this is tokyo と表示(変数展開をする) print 'this is $name'; # this is $name と表示
$ 変数 例 $a
[] 配列 例 $ab[0]
{} ハッシュ $ab{"tokyo"}
@ 配列全体 例 @ab
% ハッシュ全体 例 %a=("tokyo","03","oosaka","06");
%a=("tokyo" => "03", "oosaka" => "06");
$a{"tokyo"} は "03" を示す
$r=\%a ; $r->{"tokyo"}は"03"を示す。$rはリファレンス
=> $r={"to"=>"03","oo"=>"06"}; $r->{"to"}は"03"を示す。$rはリファレンス
@ISA 継承のスーパークラスを定義 例 @ISA (Class2);
$_ あれ foreachの変数を省略すると $_ に入る
$. 現在の行番号
$! errno の現在値またはシステムエラー文字列
() リスト 例 @ab=(123.5,234.5,45.7);
()=() 変数の交換 例 ($a,$b)=($b,$a);
[-1] 配列の最後の要素 例 $a[-1] $a[-2] 最後から2番目
[0,1] スライス 例 @a[0,1,2] は ($a[0],$a[1],$a[2]) と同じ
[0..3] 例 @a[0..2] は ($a[0],$a[1],$a[2]) と同じ
0..3 例 @a=0..2; で $aには(0,1,2)が入る
undef 未定義の値
初期化されていない変数
・数値としてみた場合は 0
・文字列としてみた場合は ""
<< ヒアドキュメント(here document)
print <<エンドトークン 文; 文; エンドトークン(end token)
例 print <<EOD "$a\n"; "$b\n"; EOD
コンテキスト ーーリストコンテキスト と スカラーコンテキスト
リストコンテキスト(配列全体を表し、値はリストになる)
リストに代入する時 例 ($cd,$ef,$gh)=@ab;
リストを代入する時 例 @ab=(123.5,234.5,45.7);
配列同士を代入する時 例 @ab=@sa;
スカラーコンテキスト(配列の要素数という1つの数値になる)
スカラー変数に代入する時 例 $su=@ab;
数値と比較する時 例 @ab > 0;
数式の一部として使う時 例 @ab+1
+= 演算 例 $a += 10; 内容 $a = $a +10;
-= *= /= **= (乗) %= (余り)
++ インクリメント 例 ++$a; 内容 $a = $a +1;
--
. 文字列の結合 例 $a = $b." ".$c; 内容 1スペース空けて結合
例 $a .= ","; 内容 末尾に,をつける
< 比較演算子
> <= >= == !=
eq 文字列として比較 例 if($a eq $b)
文字列の比較演算子
lt less than ($x lt "a") $xが"a"より小さい
gt greater than
le les than or equal ($x le "a") $xが"a"以下
ge greater then or eqal
eq equal
ne not equal
// マッチ演算子(m//) 例 if(/love/) $_が文字列の一部に一致すれば真
s///置換演算子(substitute)
s/置換え前の文字列/置換え後の文字列/ 対象はあれ($_)
例 s/abc/efg/ 文字列の置換 abc→efg
例 s/abc// 文字列の削除
tr/// 1文字単位の置換(translitarate)
例 tr/ab/xy/ a→x b→y に置換わる
例 tr/a-z/A-Z/ 小文字が大文字に変わる
例 tr/a-z/A-G/ aからgがAからGに変わり、hからzがGに変わる
例 $i=tr/a/a/; $_内のaの個数
=~ 変数の中身をマッチ
例 $a=~ tr/a-z/A-Z/;
g マッチするすべてを置換(global)
例 s/abc/efg/g
i 大文字小文字を無視する 例 s/ab/cd/ig すべての大文字と小文字
? 最小マッチ
デフォルトでは二通り以上の解釈がある場合は長いほうをとる
マッチ演算子の繰り返しに ? をつけると最小マッチに
例 /<.*?>//g タグを削除する
? 条件演算子
例 $A==0 ? expr1 : expr2
$A==0 が成立すれば expr1 を実行し、そうでなければ expr2を実行
() ()で囲んだ部分だけを抽出
例 /<(.*?)>/g
()で囲んだ部分を記憶し、$1,$2・・・という変数に順番に入る
例 s/(\S+) (\S+)/$2 $1/; 名前と苗字の入れ替え
$` マッチするまでの文字列
$& マッチした文字列
$' マッチした後の文字列
<> ダイヤモンド演算子
入力リダイレクションを渡されたときは入力から <STDIN>
ファイル名を渡されたときはファイルから
ファイル名のリストを渡されたときは、連続してレコードを読み込む
-f ファイルチェック演算子。 ファイル名なら真 例 if(-f $file)
-d ファイルチェック演算子。 ディレクトリなら真
-T ファイルチェック演算子。 テキストファイルなら真
-B ファイルチェック演算子。 バイナリーなら真
x 文字列を複数回繰り返す x 演算子。例 $b='ab'x3; $bはababab
正規表現
$ 文字列の末尾にマッチ 例 /love$/ love で終わる文字列
^ 文字列の先頭にマッチ
・・文字クラス
[abc] aかbかcのどれか 例 /[abc]/ どれかにマッチ
[a-z] 任意の小文字
[^a-z]文字クラスの否定−−動かない−−
\d 数字(digit) [0-9]と同じ
\D 数字以外 −−動かない−−
\w 英数字(word)
\W 英数字以外 −−動かない−−
\s スペース −−動かない−−
\S スペース以外
\b 単語境界(word boundary) 英数字と空白または文字列の端との間
/abc/だと"abcd"にもマッチするが
/\babc\d/だと"abc"にしかマッチしない
. 任意の一文字
繰り返し
* 0回以上の繰り返し
+ 1回以上の繰り返し
? 0回か1回 例 a?
{} 繰り返し 例 a{5} 5回繰り返し aaaaa と同じ
{,} 繰り返し 例 a{3,} 3回以上繰り返し aaa+ と同じ
例 a{3,5} 3回以上5回以下繰り返し
グループと選択
() グループ化 例 ab(cd)+ は abcd abcdcd abcdcdcd
| どれかにマッチ 例 stud(y|ies) は study studies
位置指定
^ 先頭 例 ^a
$ 末尾 例 a$
エスケープ
\ 特殊記号自身を表す時 例 \^ は ^ にマッチ
特種記号以外では書かないのと同じ
\Q \E \Qと\Eの間は、全部\が挿入されるのと同じ
例 /\Qo)^+\E/ は o)^+ と言う文字列にマッチ
スイッチ
c search-list で指定した文字以外の文字をreplace-listの1 文字に置き換え
例 $_ = 'abcABCdefDEFghi';
tr/a-z/A/c; # $_ => 'abcAAAdefAAAghi'
tr/a-z/A/cs; # $_ => 'abcAdefAghi'
d search-list にあって、replace-list に対応する置き換え文字が指定されていない文字を削除
例 $_ = 'abcABCdefDEFghi';
tr/a-z//d; # $_ => 'ABCDEF'
tr/a-z/ABC/d; # $_ => 'ABCABCDEF'
e 置換部分を Perl の式として評価し、その結果を置換文字列とする
例 $_ = "ab1234ef";s/\d+/$&*2/e; $_は"ab2468ef"
マッチした1234の*2の2468に置き換わる
g pattern と一致する部分を全て置換 例 s/abc/123/g;
i 大文字小文字を無視する 例 /ab/i
o 1 回だけコンパイル 例 s/abc/123/o
s 変換後に同じ文字が続いた場合、1 文字に圧縮
例 $_ = 'abcdABCDefghEFGH' とすると
tr/a-z/a/; # $_ => aaaaABCDaaaaEFGH
tr/a-z/a/s; # $_ => aABCDaEFGH
区切り文字を変える
m m(match)の直後の記号が区切り文字になる 例 m#///# は /\/\/\//と同じ
後方参照
カッコ () はその中の正規表現と一致した文字列を覚えていて、後からそれを
使うことができる。
「\ + 数字」でカッコと一致した文字列を参照することができる。一番左側に
ある ( )が \1 に対応し、次の ( )が \2に対応。
例 /(\w+)\s+\1/ は abc abc にマッチ。
カッコで記憶した文字列は、正規表現の外でも使うことができる。この場合、
特殊変数 $1, $2, $3, ... で取り出す。
if if(条件){命令;
}elseif(){命令;
}else{命令;
}
unless(条件){命令} 条件が偽なら・・・
while 条件が満たされている間実行
while(条件){
命令;
}
for for(最初に実行;判定;最後に実行){
命令;
}
foreach 配列要素を1個ずつ全部処理する
foreach $cd (@ab){
$sum += $cd;
}
配列@abの要素を全部たすプログラムです
redo; ループの先頭に戻る
last; ループを脱出
die 引数のメッセージを出力してプログラムが死ぬ
例 unless(@ab){die "リストが0です"}
or 真だったら次を飛ばして先に行く
例 ($a==3) or die "3以外は使えません";
and 真だったら次に行く
条件 0と""が偽
式2 if 式1; # 式1が成り立てば式2を実行
式2 unless 式1; # 式1が不成立であれば式2を実行
式2 while 式1; # 式1が成立している間、式2を実行
式2 until 式1; # 式1が不成立の間、式2を実行
print 以下は同じものを出力
print "2003 new year\n";
print "2003 "."new "."year"."\n";
print ("2003 "."new "."year"."\n");
$a=2003; print $a." new year\n";
$a=2003; print "$a new year\n";
@ARGV 引数を入れる ARGument Value
eval 文字列をPerlプログラムとして解釈
例 $a="print 2+3";
eval($a);
chomp; $_の右端の改行コードを切り落とす chomp(変数); 変数をchomp
substr 部分文字列 substr(対象文字列,開始位置,長さ)
例 substr($a,1,3); 開始位置は0から
length 文字列の長さ length(文字列) 例 length($a);
split 文字列を分割
split(/区切り文字のパターン/,区切る対象,区切る上限個数);
split(/区切り文字のパターン/,区切る対象); #すべて
split(/区切り文字のパターン/); #あれ($_)を区切る
split; #空白文字、タブで区切る
例 @a=split(/,/);
$_="123 456 789";@b=split;# @b => ("123", "456", "789")
join 文字列をつなぐ
join(間に挟む文字列,つなぐ文字列のリスト);
例 print join(",",split)."\n"; タブ区切り→カンマ区切り
glob フィル名を返す 例 $a=glob("*.txt");
system OSのコマンドを呼び出す 例 system("dir");
sort ソート 例 @a=sort(glob("*"));
qw 文字列のリストを作る(quote words)
例 @a=qw(ab cd e); は @a=("ab","cd","e"); と同じ
each ハッシュから順にデータを取り出す。取り出す順序は順不同
例 each(%a); while(($key,$value)=each(%ENV)){・・・}
keys ハッシュのキーの一覧
例 foreach $a (sort(keys(%ENV))){
values ハッシュの値の一覧を返す 例 values(%a)
delete ハッシュの要素を削除 例 delete $b{tokyo};
rand 乱数を発生 例 srand;$r=int(rand(9)); # 0から9を発生
srand 乱数シードを設定。引数が省略されると、time の値。
use English; 特種変数を名前で
$ARG $_ あれ
$INPUT_LINE_NUMBERまたは$NR $. 現在入力中の行番号
$PREMATCH $` マッチ前
$MATCH $& マッチ
$POSTMATCH $' マッチ後
$PROGRAM_NAME $0 現在実行中のプログラム名
&関数(もしあれば引数のりスト); 関数の呼び出し &は省略できる
例 &func(2,3);
sub 関数
sub 関数名{
my(引数が入る変数のリスト)=@_;
・・・・・・・
return(戻り値);
}
returnがない場合、戻り値はブロックの最後で実行された処理結果。
例 sub func{print "[@_]\n";}
my ローカル変数
@_ 引数のリストが入る配列 $_[0]で0番目の引数
push 配列の最後尾にデータを追加する
pop 配列の最後尾からデータを取り出す
shift 配列の先頭からデータを取り出す
unshift 配列の先頭にデータを追加する
pop と shift は、引数が省略されると @ARGV を操作
open ファイルのオープン open(ファイルハンドル名,"ファイル名");
ファイルの入力 open(IN1,"abc.txt");
入力 <IN1>
ファイルへの出力 open(OUT1,">abc.txt");
ファイルへの追加書 open(OUT1,">>abc.txt");
出力 print OUT1 $a;
close ファイルのクローズ close(OUT1);
select 出力ファイルハンドルを変える
select (OUT1); この後print はOUT1 へ出力
select (STDOUT); STDOUT に戻す
read 文字数を指定してファイルを読み込む
read(ファイルハンドル,読み込む変数,読み込みたい長さ)
例 while(read(IN1,$c,1)){
$a=20; $r=\$a; # 変数の前に \ をつけて、リファレンスを代入 print "\$a-->$a\n"; print "\$r-->$r\n"; print "\$\$r-->$$r\n"; # $をつけて、デリファレンス $$r $$r=1000; # $$rにも、代入できる print "\$\$r-->$$r\n"; print "\$a-->$a\n";実行結果
@a = (10, 20, 30, 40);
$ra = \@a; # $ra は @a へのリファレンス
print @$ra."\n"; # 配列全体を表示(配列の個数 4 を表示)
print $$ra[0]."\n"; # 0 番目の要素 10 を表示
print $ra->[1]."\n"; # 矢印演算子 (1 番目の要素 20 を表示)
print ${$ra}[2]."\n"; # ブロック {} を使う(2 番目の要素 30 を表示)
print ${$ra[3]}."\n"; # 何も表示されない
@ra = \(10, 20, 30, 40); # 各要素のリファレンスを格納するリストを生成
print ${$ra[3]}."\n"; # 3 番目の要素をデリファレンス (40 を表示)
%h = ("abc"=>10, "def"=>20, "ghi"=>30, "op"=>40);
$rh = \%h; # リファレンス
print %h."\n"; # 4/8 と表示
print $rh."\n"; # HASH(0x1832884) と表示
print %$rh."\n"; # 4/8 と表示。ハッシュ全体を表示
print $rh->{"abc"}."\n\n"; # 10 と表示。$$rh{"abc"} と同じ
$r = {"abc"=>10, "def"=>20, "ghi"=>30, "op"=>40};
print $r."\n"; # 4HASH(0x183f14c) と表示。$rはリファレンス
print $$r{"abc"}."\n"; # 10 と表示
print $r->{"abc"}."\n"; # 10 と表示
while(read(STDIN,$c,1)){
print unpack("H2",$c); #H2は2桁の16進数
print "\n";
}
print &add(3, 5); #サブルーチンを呼び出す
#サブルーチンの宣言
sub add {
return($_[0] + $_[1]);
}
$a = 100 ;
&add_10 ( *a ); # 型グロブの渡し
print $a ; # 表示 → 110
sub add_10{
local *b = $_[0] ; # 引数の取得
$b = 10+$b ; # 変数の更新
}$a = 100 ;
&add_10 ( \$a ) ; # リファレンス渡し
print $a ; # 表示 → 110
sub add_10 {
my $b = $_[0] ; # 参照渡しの受け取り
$$b = 10 + $$b; # デリファレンスして代入($aへの代入と同じ)
}
package calc; #ライブラリで用いる名前空間名
sub add {
return($_[0] + $_[1]);
}
1;
ライブラリーの利用例require "calc.pl"; #ライブラリの使用を宣言する(必須) print &calc'add(3, 5); #パッケージ内のサブルーチンや変数は、「パッケージ名'名前」で指定
package Point; # クラス名 Point を作成
sub new { # コンストラクタの作成(インスタンスを生成するメソッド)
my $class = shift; # 第1引数のクラス名を受け取る
my ($x,$y) = @_;
my $obj={"x"=>$x,"y"=>$y};# オブジェクト。ハッシュのリファレンスを作成
bless $obj, $class; # bless 関数。
return $obj; # オブジェクトのリファレンスを返す
}
sub distance { # メソッドの作成(2点間の距離を計算)
my ($obj1, $obj2) = @_;
my $dx=$obj1->{"x"}-$obj2->{"x"};
my $dy=$obj1->{'y'}-$obj2->{'y'};
sqrt( $dx * $dx + $dy * $dy );
}
package main;
$obj = new Point(10,20); # クラスのオブジェクトリファレンスを作成
print $obj->{"x"}."\t".$obj->{"y"}."\n"; # 10 20 と表示
$p1 = new Point(0,0);
$p2 = Point->new( 10, 10 );
$len1 = $p1->distance( $p2 );
$len2 = distance $p1( $p2 );
print "$len1 $len2\n"; # 14.142135623731 14.142135623731と表示
package A;
sub new { # インスタンスの生成
my ($type,$a,$b) = @_;
my $obj = {'a'=>$a,'b'=>$b };
bless $obj, $type;
$obj;
}
sub get_a { # アクセスメソッド
my $obj = shift;
$obj->{'a'};
}
sub get_b { # アクセスメソッド
my $obj = shift;
$obj->{'b'};
}
package B;
@ISA = (A); # A を継承
sub new { # インスタンスの生成
my ($type, $a, $b, $c) = @_;
my $obj = $type->SUPER::new($a,$b);
$obj->{'c'} = $c;
$obj;
}
sub get_c { # アクセスメソッド
my $obj = shift;
return $obj->{'c'};
}
$o1 = A->new( 1 ,2);
$o2 = B->new( 10, 20 ,30);
print $o1->get_a(), "\n"; # 1 を出力
print $o2->get_a(), "\n"; # 10 を出力
print $o2->get_c(), "\n"; # 30 を出力
# cat.pl
while(<>){ print; }
>perl cat.pl test.txt test2.txt# cat.pl
while(<>){ print "$.: $_"; }
>perl cat.pl test.txt test2.txt
>copy con test3.txt
abc
test3.txt を上書きしますか? (Yes/No/All): y
abc
erg
^Z
1 個のファイルをコピーしました。
>copy test3.txt con
abc
abc
erg
1 個のファイルをコピーしました。>dir > test3.txt >copy test3.txt con ドライブ C のボリューム ラベルは *** です ボリューム シリアル番号は *** です C:\test のディレクトリ 2003/03/05 11:34. 2003/03/05 11:34 .. 2003/03/05 11:21 40 cat.pl 2003/03/05 11:24 371 cat.pl.html 2003/03/05 11:22 16 test.txt 2003/03/05 11:22 17 test2.txt 2003/03/05 11:40 0 test3.txt 5 個のファイル 444 バイト 2 個のディレクトリ *** バイトの空き領域 1 個のファイルをコピーしました。
@a=0..4;
print "@a\n"; # 0 1 2 3 4 と表示
($c,$d,@e)=@a;
print "$c\n"; # 0 と表示
print "@e\n"; # 2 3 4 と表示
@f=@a[0,1,4];
print "@f\n"; # 0 1 4 と表示
@g=@a[1..3];
print "@g\n"; # 1 2 3 と表示
$h=@a;
print "$h\n"; # 5 と表示(スカラーに変換し、要素数となる)
# foreach
$sum = 0;
foreach $i (@a){
$sum += $i;
}
print "$sum\n"; # 10 と表示(0 1 2 3 4 の合計)
open(IN, "test.txt");
@data = <IN>; # test.txt の内容をすべて@dataに読み込む
close(IN);
print "@data\n"; # test.txt の内容を表示
@array = ();
for( $i = 0; $i < 2; $i++ ){
push( @array, $i ); # 最後尾にデータを追加
print "[@array]\n";
}
while( @array ){
$i = pop( @array ); # 最後尾からデータを取り出す
print "$i [@array]\n";
}
for( $i = 0; $i < 2; $i++ ){
unshift( @array, $i ); # 先頭にデータを追加
print "[@array]\n";
}
while( @array ){
$i = shift( @array ); # 先頭からデータを取り出す
print "$i [@array]\n";
}
動作結果# test.pl print "$0\n"; print "[@ARGV]\n";>perl test.pl abc ef hij
while(<>){
if (/[abc]/){print "ok\n";} # aかbかcのどれか
else {print "ng\n";}
}
# test.pl
$pattern = shift;
$filename = shift;
open( IN, $filename );
while( <IN> ){
if( /$pattern/ ){
print "$.: $_"; # 正規表現と一致して行番号と行の内容
print "$&\n"; # 正規表現と一致した文字列
print "$`\n"; # 一致した文字列の前の文字列
print "$'\n"; # 一致した文字列の後の文字列
}
}
close( IN );
実行結果# numadd.pl 行番号をつける
$filename = shift; # ファイル名
open( IN,$filename );
@a=<IN>; # ファイルの内容をすべて@a に読み込む
close( IN );
$line_num=1; # 初期化
open (OUT,">$filename");
close (OUT);
open (OUT,">>$filename");
foreach (@a){
select (OUT);
printf ("%4d ", $line_num++);
print ;
}
close (OUT);
# numdell.pl : 行番号を削除
$filename = shift; # ファイル名
open( IN,$filename );
@a=<IN>; # ファイルの内容をすべて@a に読み込む
close( IN );
@b=(); # 初期化
foreach (@a){
$_=~ s/\ +\d+\ //; # スペース、数字、スペース
push( @b,$_); # @b の最後尾に追加
}
open (OUT,">$filename");
print OUT @b;
close (OUT);
# 階乗を計算する
sub fact {
my $n = shift;
$n == 0 ? 1 : $n * &fact( $n - 1 );
}
$a=&fact(4);
print "$a\n"; # 24 と表示
┌ 1 n = 0
f(n) = ─┤ 1 n = 1
└ f(n-1) + f(n-2) n > 1
# フィボナッチ関数
sub fibo {
my $x = shift;
($x == 0 || $x == 1) ? 1 : &fibo($x - 1) + &fibo($x - 2);
}
$a=&fibo(5);
print "$a\n"; # 8 と表示
# フィボナッチ関数
sub fibo {
my $x = shift;
($x == 0 || $x == 1) ? 1 : &fibo($x - 1) + &fibo($x - 2);
}
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
print "開始時刻$hour:$min:$sec\n";
$a=&fibo(40);
print "$a\n";
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
print "終了時刻$hour:$min:$sec\n";
実行結果# ハノイの塔
sub hanoi {
my ($n, $from, $to, $via) = @_;
if($n == 1){
print "$from の円盤 $n を $to へ移動\n";# n 枚目の円盤を from から to へ移す
} else {
hanoi($n - 1, $from, $via, $to );# n - 1 枚の円盤を from から via に移す
print "$from の円盤 $n を $to へ移動\n";
hanoi($n - 1, $via, $to, $from );# n - 1 枚の円盤を via から to へ移す
}
}
&hanoi( 3, 'From', 'To ', 'via ' );
実行結果From の円盤 1 を To へ移動 From の円盤 2 を via へ移動 To の円盤 1 を via へ移動 From の円盤 3 を To へ移動 via の円盤 1 を From へ移動 via の円盤 2 を To へ移動 From の円盤 1 を To へ移動