perl (Practical Extraction and Report Language) は、インタプリタであり、またスクリプト言語でもあります。
もちろんオープンソースですので、ここからダウンロードして自由につかえます。
プログラムをファイルに格納する場合は、拡張子として .pl を使います。
ここで "Hello world !" を印刷するプログラムを考えてみましょう。
#!/usr/local/bin/perl -w use strict; 文法チェックを厳格にする print "Hello world !\n"; [ 実行結果 ] > perl hello.pl Hello world !
| 文 | 動作 | 例 |
|---|---|---|
| if 条件 {文}; | 条件が真なら文を実行 | if (! open(FOUT,">$out_file")) {
&err_out("can\'t open $out_file");
exit(3);
} |
| 式 if 条件; | 条件が真なら式を実行 | print "file is empty\n" if -z $filenm; |
| 式 unless 条件; | 条件が偽なら式を実行 | $reject++,next unless $good; |
| 式 while 条件; | 条件が真の間、式を実行 | print $line while ($line = <>); |
| 式 until 条件; | 条件が偽の間、式を実行 | $reject++ unless $good; |
| while (条件) { ループ本体 } |
条件が真の間、 ループ本体を実行 |
while ($data eq $prev) {
$prev = $data;
$data =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/gei;
} |
| for (式1; 式2; 式3) { ループ本体 } |
式2 が真の間、 ループ本体を実行 |
@array = ('aaa','bbb','ccc');
for ($i=0; $i<=$#array; $i++) {
print $array[$i],"\n";
}
|
| foreach 変数 (リスト) { ループ本体 } |
変数に値の間、 ループ本体を実行 |
@languages = ('Eng','Jap','Ger');
foreach $name (@languages) {
print $name,"\n";
}
|
| 式1; while (式2) { ループ本体 } continue { 式3; } |
上記 for 文と同じ | $longest = 0;
while ($line = <>) {
chomp $line;
$len =length($line);
if ($longest < $len) {
$longest = $len;
}
}
print "Longest line is $longest\n";
|
| do ブロック while 条件; | ブロック実行後、条件が真の間 ブロックを実行 |
|
| do ブロック until 条件; | ブロック実行後、条件が偽の間 ブロックを実行 |
|
| & サブルーチン(); | サブルーチンよびだし | & mk_date(); |
| do ファイル名; | ファイルを perl プログラムとして実行 | |
| goto ラベル; | ラベルにとぶ | goto notfound; |
| next ラベル; | ループを出て continue ブロックを 実行して次のループを実行します ラベルでループブロックを指定できます |
while (<>) {
:
next if ($cnt <7);
} |
| redo; | 現在のループをやり直します | redo; |
| last; | ループを中止します。c の break と同じ | while (<>) {
:
last if ($cnt > $MAX);
} |
| continue ブロック | while,until で使え 各ループの最後で実行される |
continue; |
| exit(終了コード); | 終了コードで実行を終わる | exit(10); |
| # 文字列 | コメント | # This is a comment |
perl のサブルーチンの戻り値は通常 1 が成功、0 が失敗です。
| 項目 | 書式 | 例 |
|---|---|---|
| 定義 | sub 名前 {
ブロック 定義
}
引数は @_
または $_[0] ... $_[n]
局所変数(レキシカル変数)は my (変数リスト);
また @_ で引数を受ける場合は、
レキシカル変数が1つでも括弧で囲む必要があります
my $aaa=1; 宣言して初期化する
my ($arg1,$arg2) = @_ ; 引数のセット
引数が @a1,@a2 の場合は、受け渡しが複雑(参照)
& sb_call(\@a1,\@a2);
sub sb_call {
my ($arg1,$arg2) = @_ ;
my (@p__1,@p__2);
@p__1 = @$arg1; 元の配列と同じ
@p__2 = @$arg2; 元の配列と同じ
サンプル t_sbb.pl
|
sub prt_max2 {
my ($max,$min)=@_; 引数を局所変数に設定
$max = $min if $min > $max;
print " $max\n"
}
|
| 参照 | & サブルーチン名(引数列); | $mmm = &prt_max(12,345); |
![]() |
![]() |
| 演算子 | 説明 | 例 |
|---|---|---|
| ++,-- | インクリメント、デクリメント | $cnt++; |
| ** | べき乗 | $cnt**; |
| !,~,- | 真偽否定、ビット反転、マイナス | $a++ if (! $a); |
| *,/,%,x | 乗、除、剰余、繰り返し | $rem = int($dno % $SZ_ITEM); 剰余は int 変換すること |
| +,- | 加、減 | $a = $c + $b; |
| <<,>> | ビットシフト | $s = $a << 2; |
| <,>,<=,>= | 比較 | if ($cnt > $end) $ExitValue = 0; |
| ==,!=,<=> | 比較 | if (($len == 0) || ($len == 1)) next; |
| & | ビットごとの and | $bit = $bit_a & $bit_b; |
| |,^ | ビットごとの or,ex or | $bit = $bit_a | $bit_b; |
| && | and | $c ++ if ($a && $b); |
| || | or | $c ++ if ($a || $b); |
| ..,... | 範囲演算子 | print $a(1 .. 3) |
| ? : | 条件演算子 | $max = ($max>$cur) ? $max : $cur |
| =,+=,-= | 代入演算子 | $end = $start + $MAX; |
| , | コンマ演算子 | $a=1,$b=2,$c=3; |
![]() |
![]() |
| 演算子 | 説明 | 例 |
|---|---|---|
| =~,!~ | パターン指定 | $a = $b =~ /pat/; $c !~ /pat/; |
| . | 文字列結合 | $c = $a . $b; |
| lt,gt,le,ge,eq,ne,cmp | 文字列比較 | print "data1 equal data2\n" if ($data1 eq $data2); |
![]() |
![]() |
| 演算子 | 説明 | 例 |
|---|---|---|
| -r | 実効 uid/gid で読み込み可能 | print "読み込み可\n" if -r $filenm; |
| -w | 実効 uid/gid で書き込み可能 | print "書き込み可\n" if -w $filenm; |
| -x | 実効 uid/gid で実行可能 | print "実行可\n" if -x $filenm; |
| -o | 所有者が実効 uid | print "所有\n" if -o $filenm; |
| -R | 実 uid/gid で読み込み可能 | print "読み込み可\n" if -R $filenm; |
| -W | 実 uid/gid で書き込み可能 | print "書き込み可\n" if -W $filenm; |
| -X | 実 uid/gid で実行可能 | print "実行可\n" if -X $filenm; |
| -O | 所有者が実 uid | print "所有\n" if -O $filenm; |
| -e | ファイルが存在する | print "ファイルが存在する\n" if -e $filenm; |
| -z | ファイルが空 | print "ファイルが空\n" if -z $filenm; |
| -s | ファイルが空でない(サイズを返す) | print "ファイルが空でない\n" if -s $filenm; |
| -f | 普通のファイル | print "普通のファイル\n" if -f $filenm; |
| -d | ディレクトリ | print "ディレクトリ\n" if -d $filenm; |
| -l | シンボリックリンク | print "シンボリックリンク\n" if -l $filenm; |
| -p | 名前つきパイプ (FIFO) | print "名前つきパイプ\n" if -p $filenm; |
| -s | ソケット | print "ソケット\n" if -s $filenm; |
| -b | ブロックデバイス | print "ブロックデバイス\n" if -b $filenm; |
| -c | キャラクタデバイス | print "キャラクタデバイス\n" if -c $filenm; |
| -u | setuid ビットが立っている | print "setuid ビットオン\n" if -u $filenm; |
| -g | setgid ビットが立っている | print "setuid ビットオン\n" if -g $filenm; |
| -k | sticky ビットが立っている | print "sticky ビットオン\n" if -k $filenm; |
| -t | ファイルハンドルが tty である | print "tty\n" if -t $filenm; |
| -T | テキストファイル | print "テキストファイル\n" if -T $filenm; |
| -B | バイナリファイル | print "バイナリファイル\n" if -B $filenm; |
| -M | 最終更新時刻からスクリプト開始 までの日数 |
print "普通のファイル\n" if -f $filenm; |
| -A | 最終アクセス時刻からスクリプト開始 までの日数 |
print "普通のファイル\n" if -f $filenm; |
| -C | 最終 i ノード更新時刻からスクリプト 開始までの日数 |
print "普通のファイル\n" if -f $filenm; |
![]() |
![]() |
| マッチ | XXX ~ /正規表現/修飾子; | if (STRING =~ /PATTERN/) ...; |
| 非マッチ | XXX !~ /正規表現/修飾子; | if (STRING !~ /PATTERN/) ...; |
| 置換 | s/正規表現/置換文字/修飾子; | $var =~ s/PATTERN/REPLACEMENT/; |
| 修飾子 | g 繰り返してマッチ i 英字の大文字、小文字を区別しない m 文字列を複数行として扱う o PATTERNのコンパイルを 1回だけにする s ワイルドカードのドット( . )が改行にもマッチするようにする x パターン内の空白を無視し、# 以降の文字列をコメントとします e 式の右側の評価を行なう ee 式の右側の評価を行い、実行後の戻り値を再度評価する |
$var =~ s/[A-Z]/[a-z]g |
マッチの場合、パターン中のグループは変数 $1,$2,.... に残ります。
量指定子には、欲張り指定子と非欲張り指定子があります。 欲張り指定子は、"*,+,?,{}" などで、 非欲張り指定子は、"*?,+?,??,{}?" などです。
[例 1] system message からあるパターンを取り出す
open(IN,"/usr/adm/messages");
while ($line = <IN>) {
next if $line !~ /not responding still trying/;
$line =~ / (\d\d:\d\d:\d\d) .*sever (.*) not/;
print "$1 $2\n";
}
close(IN);
[例 2] 先頭の2単語を swap
s/^([^ ]+) +([^ ]+)/$2 $1/;
[例 3] 80 文字以上の行
/.{80,}/*
[例 4] encode and decode
encode では、英数字以外を %XX に変換する
decode では、%XX%XX を バイナリに変換する
$str =~ s/(\W)/sprintf("%%%02X",unpack("C",$1))/eg; encode
$str =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/ge; decode
一般的な正規表現は、ここを参照してください。 ここでは、perl に限定した事項を書きます。
| メタ文字 | 説 明 | |
|---|---|---|
| \d | 数字の1文字にマッチ | [0-9] と同じです |
| \D | 数字以外の1文字にマッチ | [^0-9] と同じです |
| \w | アルファベットまたは数字(単語)の1文字にマッチ | [a-zA-Z_0-9] と同じです |
| \W | アルファベットと数字以外(単語以外)の1文字にマッチ | [^a-zA-Z_0-9] と同じです |
| \s | 空白文字にマッチ(スペース、タブ、改行) | [ \n\r\f\t] と同じです |
| \S | 空白文字以外にマッチ | [^ \n\r\f\t] と同じです |
| (?:…) | 後方参照を行わないグループ化 | \1 や \2 を使用した後方参照が出来ません |
カッコは、文字や正規表現をグループにまとめます。 また、グループにマッチした文字列は記録され、 特別な変数によって参照できます。これを後方参照といいます。 参照の仕方は、カッコで囲んだグループの左から順に、\1、 \2、\3... となります。
たとえば、Attension!のようなHTMLタグにマッチさせるには次のようになります。
m|<(.*?)>.*?\1>|
もしタグが<b>であれば、(.*?) の部分に b がマッチし、\1 は b の値になります。 その場合は「<b>任意の文字列</b>」というパターンにマッチします。 タグが <html> であれば、「<html>任意の文字列</html>」となります。
正規表現の外部では、特殊変数を使って $1、 $2、$3... で参照できます。
$str = "Now I know His strength is within me"; $str =~ /^(\w+)/; # 先頭の単語にマッチ print $1, "\n"; # マッチした値を表示 >Now
後方参照の変数には上記のほかに、マッチ変数 $& $` $' $+ があります。 これらの変数を使うとプログラム内のすべての正規表現の処理が遅くなるので、 注意して使ってください。
マッチ変数の一覧
| メタ文字 | 説明 |
|---|---|
| $& | 文字列の中でパターン全体がマッチした部分を参照 |
| $` | 文字列の中でマッチに先行する部分を参照 |
| $' | 文字列の中でマッチに続く部分を参照 |
| $+ | 最後にマッチした文字列を返す |
マッチ変数の使い方
# 最後にマッチしたワードを配列に格納
while ( /\w+/g ){ push( @words, $& ) }
選択一致パターンの | は、文字列のグループ化と組み合わせて使うと効果的です。 たとえば、Windows Me か Windows Xp という単語を探したい場合は、 次のように書くことができます。
/Windows (Me|Xp)/
ただ、グループ化すると自動的に後方参照用に記憶されるので、 多少ではありますが処理が遅くなります。 これを避けるには、後方参照を行わないグループ化の構文「(?:…)」を使います。
/Windows (?:Me|Xp)/ # マッチしたデータは記憶されない
アンカーは、行頭や行末など、文字列中の位置にマッチします。
| メタ文字 | 説明 |
|---|---|
| ^ | 行頭 |
| $ | 行末 |
| \A | 文字列の先頭 |
| \b | 単語の区切り:ここで単語とは、英数字とアンダースコア( _ )です |
| \B | 単語の区切り以外 |
| \G | 文字列の先頭、もしくは修飾子 g がついたパターンマッチングが終了した場所 |
| \Z | 文字列の最後 |
\A と ^ 、\Z と $ は機能がよく似ているので注意してください。 複数の行がある文字列を対象に正規表現を行った場合、 ^ は改行の直後にもマッチしますが、\A は文字列の先頭にしかマッチしません。
\Z と $ の関係も \A と ^ に似ています。 $ は改行の直前にもマッチしますが、\Z は文字列の最後にしかマッチングしません。
\b は、ワード境界とマッチします。ワード境界とは、\w と \W の間を指します。 利便性のため、文字列の先頭と末尾もワード境界とされます。
[ 例 ]
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_reg.pl
#-----------------------------------------------------
use strict;
my ($year,$month,$day);
my ($s1,$s2,$s3);
my @data1 = (
'2004-10-01','04-01-01');
my @data2 = (
'The lio_listio function allows the calling process',
'close(2), exec(2), exit(2), fork(2), lseek(2)',
'SunOS 5.7 Last change: 22 Jun 1998');
foreach (@data1) {
($year, $month, $day) = /(\d+)-(\d+)-(\d+)/;
print "\ndata is [$_]\t=======\n";
print "$year/$month/$day\n";
}
foreach (@data2) {
($s1,$s2,$s3) = ( /^(\S+)\s+(\S+)\s*(.*)/ );
print "\ndata is [$_]\t=======\n";
print "1=$s1 \n";
print "2=$s2 \n";
print "3=$s3 \n";
}
[ 実行結果 ]
> perl t_reg.pl
data is [2004-10-01] =======
2004/10/01
data is [04-01-01] =======
04/01/01
data is [The lio_listio function allows the calling process] =======
1=The
2=lio_listio
3=function allows the calling process
data is [close(2), exec(2), exit(2), fork(2), lseek(2)] =======
1=close(2),
2=exec(2),
3=exit(2), fork(2), lseek(2)
data is [SunOS 5.7 Last change: 22 Jun 1998] =======
1=SunOS
2=5.7
3=Last change: 22 Jun 1998
![]() |
![]() |
[ 宣言 ] 局所変数は通常 my で宣言する。 複数の変数を1つの my で宣言する場合は、() で囲みます。 宣言して初期化することも可能でが、この場合は1つづつ書きます。 local で宣言しなければならないのは、特殊変数(perl でグローバルに宣言されている) をサブルーチン内で局所的に使いたい場合などです。($_) my と比較して local はコストが高くつきます。 [ 例 ] my ($hostname,$username,$password,$srcdir,$logfile); my $ret = 1;
| 項目 | 種別 | 演算子 | 例 1 | 例 2 | 結果 |
|---|---|---|---|---|---|
| 宣言 | スカラ変数 | $ | $scalar | $scalar = 10; | 10 |
| 配列 | @ | @array | @array = ('Sun','Mon','Tue'); | ||
| 連想配列:ハッシュ | % | %ass_array | %ass_array = ('smtp',25,'finger',79); | ||
| リファレンス(参照) | \ | $ref_array | $ref_array = \@array; | ||
| 参照 | スカラ変数 | $ | $scalar | print "$scalar \n"; | 10 |
| 配列要素 配列(一部) 配列要素数-1 |
[ ] | $array[$index] @array[$from .. $to] $#array |
print "$array[1]\n"; print "@array[0 .. 2]\n"; print "$#array\n" |
Mon SunMonTue 2 | |
| 連想配列要素 | { } | $ass_array{$index} $ass_array->{$index} |
print "$ass_array{"smtp"}\n"; print "$ass_array->{"smtp"}\n"; |
25 | |
| デリファレンス | $/@/%/& | @$ref_array | print "@$ref_array\n"; | SunMonTue |
perl は、文字列と数値を区別しませんので、
同一の配列に文字列と数値を一緒に代入できます。
また配列の添え字は、0 からはじまり、$# 配列名までです。
従って配列のサイズは、($# 配列名 +1) です。
$# 配列名に以前より大きい値を代入すると、サイズは大きくなります。 また小さい値を代入すると、サイズは小さくなります。
また undef $color[2] とすると、配列の要素数は変わりませんが、 2番目の値には未定義が格納されます。
配列の要素は [ ] で囲んで指定します。
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_var.pl
#-----------------------------------------------------
use strict;
my $scalar = 10;
my @array = ('Sun','Mon','Tue');
my %ass_array = ('smtp',25,'finger',79);
my @empsalary = ('Jone',23000,'Tiger',30000);
print $scalar ,"\n";
print $array[1],"\n";
print @array[0 ... 2],"\n";
print @array[0,2],"\n";
print $ass_array{"smtp"},"\n";
print @empsalary[0 ... 1],"\n";
print $#empsalary,"\n";
[ 実行結果 ]
> perl t_var.pl
10
Mon
SunMonTue
SunMonTue
25
Jone23000
3
多次元配列は一元配列を拡張することで、実現できます。
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_array.pl
# Function :
#-----------------------------------------------------
use strict;
my @two = ([3,7,5],[8,6,1],[4,2,9]);
$\ = " ";
print "";
print "[0,1] = $two[0][1]\n";
print "[2,2] = $two[2][2]\n";
print "[1] = @{$two[1]}\n";
exit(0);
[ 実行結果 ]
> perl t_array.pl
[0,1] = 7
[2,2] = 9
[1] = 8 6 1
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_assary.pl
#-----------------------------------------------------
my %assary = ('aaa',1000,'bbb',2000,'ccc',3000);
my @elem = ('aaa','bbb','ccc');
foreach $aele (@elem) {
print $assary{$aele},"\n";
}
[ 実行結果 ]
> perl t_assary.pl
1000
2000
3000
![]() |
![]() |
リストは、スカラコンテキストでの評価を除けば、配列と同じ振る舞いをします。
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_list.pl
#-----------------------------------------------------
my @subjects = ('Biology','Chemistry','Matematics');
my @empty = ();
my @lang;
my ($first,$second) = (1,2);
my ($page,$edition,$version) = ( 1, 2, 3, 4, 5);
my ($data1,$data2,@data3) = ( 1, 2, 3, 4, 5);
my ($dat11,$dat22,@dat33) = ( 1 .. 4);
my @card = ('Jack','Queen','King');
my $num = @card;
my ($first_card) = @card;
my @array = ('aaa','bbb','ccc');
my @n1 = @array;
my @n2 = ('aaa','bbb','ccc');
($subjects[3],$subjects[5]) = ('Education','History');
@subjects[0,3..5] = ('Music','Geology','Economics','Sociology');
(@lang[1,3]) = ('Greek','Italy');
print "subjects = @subjects \n";
print "empty = @empty \n";
print "first,second= $first ,$second \n";
print "page,edition,version = $page,$edition,$version\n";
print "data1,data2,data3 = $data1,$data2,@data3\n";
print "dat11,dat22,dat33 = $dat11,$dat22,@dat33\n";
print "lang_0,lang_1,lang_3 = $lang[0],$lang[1],$lang[3]\n";
print "subjects_0,subjects_1,subjects_2,subjects_3 = $subjects[0],$subjects[1],$subjects[2],$subjects[3]\n";
print "card = @card\n";
print "num = $num\n";
print "first_card = $first_card\n";
print "array = @array\n";
print "n1 = @n1\n";
print "n2 = @n2\n";
[ 実行結果 ]
> perl t_list.pl
subjects = Music Chemistry Matematics Geology Economics Sociology
empty =
first,second= 1 ,2
page,edition,version = 1,2,3
data1,data2,data3 = 1,2,3 4 5
dat11,dat22,dat33 = 1,2,3 4
Use of uninitialized value at t_list.pl line 30.
lang_0,lang_1,lang_3 = ,Greek,Italy
subjects_0,subjects_1,subjects_2,subjects_3 = Music,Chemistry,Matematics,Geology
card = Jack Queen King
num = 3
first_card = Jack
array = aaa bbb ccc
n1 = aaa bbb ccc
n2 = aaa bbb ccc
詳細はここを参照してください。
ハッシュ変数は、配列のインデックスが文字列となったもので、 このインデックスをキーと呼びます。 ハッシュでは要素の値はキーによって管理されます。
ハッシュを宣言するときは変数名の前にパーセント( % )を付けます。 ハッシュは、 { } でキーを囲みます。 複数の値を一度にハッシュへ代入するには、キー、値の順番で記述します。 => 演算子を使うと読みやすくなります。
$hash{'Akai'} = 'akai@domain.com';
$hash{'Ishikawa'} = 'ishi@domain.com';
$hash{'Ueda'} = 'ueda@domain.com';
%hash = ('Akai', 'akai@domain.com', 'Ishikawa', 'ishi@domain.com');
%hash = (
"Akai" => "akai@domain.com",
"ihikawa" => "ishi@domain.com",
);
%hash = ('Akai', 'akai@domain.com', 'Ishikawa', 'ishi@domain.com');
| 関数名 | 働き | 例 |
|---|---|---|
| keys | ハッシュ変数のすべてのキーをリスト値として返します ハッシュの要素数を調べる |
@key = keys( %hash ); $n = keys( %hash ); |
| values | ハッシュ変数のすべての値をリストにして返します | @value = values( %hash ); |
| sort | keys 関数が任意にリスト化したキーの順番を、文字コード順で並び替える | foreach $key ( sort keys %hash ) {
print "key:$key\tvalue:$hash{$key}", "\n";
}
[ 実行結果 ]
key:Akai value:akai@domain.com
key:Ishikawa value:ishi@domain.com |
| each | ハッシュから次の要素を取り出して、キーと値のペアを返します。 すべての要素を取り出すと、未定義を返します | while ( ($key, $value) = each(%hash) ) {
print "key:$key\tvalue:$value\n";
}
[ 実行結果 ]
key:Ishikawa value:ishi@domain.com
key:Akai value:akai@domain.com |
| exists | 指定したキーの値があるかを調べる | if (exists($count{$key}) ) {
...
} |
| delete | ハッシュの消去 | delete $hash{'Akai'}; |
![]() |
![]() |
(m) のついていない変数はグローバル変数です。 サブルーチン内で使用する場合は local 宣言することをお薦めします。
| 特殊変数 | 意味 | 既定値 |
|---|---|---|
| $$ | perl 自身のプロセス ID | |
| $( | perl の実グループ ID | |
| $) | perl の実効グループ ID | |
| $< | perl の実ユーザ ID | |
| $> | perl の実効ユーザ ID | |
| $0 | 実行中のスクリプトファイル名 | |
| $! | システムコール呼び出し時に発生したエラー番号またはエラーメッセージ | |
| $@ | eval,do,require 中で発生したエラーメッセージ | |
| $? | system,`...`,パイプを閉じたときのプロセス終了値 実際の exit 値を得るには 256 で割らなければならない |
|
| $" | ダブルクオート中でリストを展開する時の要素間の区切り文字列 | ' ' |
| $# | print で数値を出力する書式 | %.20g |
| $, | print 時引数間の区切り文字列 | ',' |
| $/ | 入力レコード区切り文字列 | '\n' |
| $\ | 出力レコード区切り文字列 | '' |
| $% (f) | write 時の現在のページ番号 | |
| $- (f) | write 時の現ページの残りの行数 | |
| $= (f) | write 時参照される1ページの行数 | 60 |
| $^ (f) | ページ先頭の出力に使う書式の名前 | |
| $~ (f) | 現書式の名前 | |
| $| (f) | ファイルハンドルに対し print,write の出力をフラッシュするか 0 はフラッシュしない、非0はフラッシュする |
0 |
| $. | 最後のファイル読み取り時の行番号 | |
| $; | 多次元配列をエミュレートする時の区切り文字列 | '\n' |
| $[ | 配列の最初の添え字 | 0 |
| $1,$2,..,$9 (m) | 正規表現照合時に n 番目にマッチした内容が $n に格納される | |
| $& (m) | 直前の正規表現照合時にマッチした文字列全体 | |
| $' (m) | 直前の正規表現照合時にマッチした文字列より前の部分 | |
| $' (m) | 直前の正規表現照合時にマッチした文字列より後ろの部分 | |
| $+ (m) | 直前の正規表現照合時 (...) にマッチした最後の内容 特に | と (...) を組み合わせた時、 どのパターンにマッチしたかを調べるときに有用 |
|
| $* (m) | 正規表現で複数行照会を行う場合非0にする | |
| $_ | 組み込み手続きでの省略時の引数 サブルーチンで使う場合、local 宣言しなければなりません グローバル変数なので、前置がうわがきされてしまうからです |
local $_;
foreach (@list) {
print $_;
} |
| @_ | ユーザ定義関数への引数リスト | |
| $] | perl のバージョンを識別する文字列 | |
| $^D | -D で指定したデバッグレベル | |
| $^F | システムファイルディスクリプタの最大数 | 2 |
| $^I | -i で作られるバックアップファイルの拡張子 | |
| $^L | 書式出力時の改ページ文字 | |
| $^T | perl 実行開始時刻 | |
| $^W | -w が指定されていると1 | |
| $^X | perl 自身の絶対パス | |
注意
| (f) | 出力ファイルハンドル依存な変数 |
| (m) | 直前のパターンマッチの結果を格納する局所変数 |
$string = "And little lambs eat ivy"; $string =~ /l[^s]*s/; print "($`) ($&) ($')\n"; (And ) (little lambs) ( eat ivy)
![]() |
![]() |
| 既定義変数 | 意 味 | 使用法 |
|---|---|---|
| @ARGV | コマンド行引数 |
while ($arg = shift(@ARGV)) {
print "$arg ";
} |
| $#ARGV | コマンド行引数の数-1 | print "$#ARGV"; -1 : ないとき |
| DATA | ファイル・ハンドル DATA はスクリプトファイル中 __END__ より後ろの部分を読み出す | while ( <DATA> ) {
print $_;
}
__END__
data1
data2 |
| %ENV | 環境変数を保持する連想配列。キーは変数名、値は変数値 | $ENV{'LANG'} |
| @F | -a スイッチ指定時 split された文字列を格納する | |
| @INC | require,do でスクリプトファイルを検索するディレクトリ | |
| %INC | require,do でスクリプトファイルを読み込んだ時 ファイル名がキー、パス名が値として %INC に格納される |
|
| STDIN STDOUT STDERR |
標準入出力/エラーのファイル・ハンドル | $file = |
![]() |
![]() |
| シンボル | 機能 |
|---|---|
| __END__ | スクリプトの終わりを示す。 |
| __FILE__ | 現在のスクリプトファイル名 |
| __LINE__ | 現在のスクリプト中の行番号 |
| __DATA__ | DATA ハンドルが読み込むデータの開始位置 |
![]() |
![]() |
リファレンスは、変数、関数などのアドレスをとりだすことです。
\ 演算子でリファレンスを作成できます。
my @list1=(1,2,3); my @list2=(4,5,6); func(\@list1,\@list2);
リファレンスをデリファレンスするには、それぞれの変数記号をつけます。 デリファレンスは、アドレスから実体をとりだすことです。
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_func.pl
# Function :
#-----------------------------------------------------
use strict;
my @list1 = (1,2,3);
my @list2 = (4,5,6);
& func_ref(\@list1,\@list2);
exit(0);
sub func_ref {
my ($ref1,$ref2) = @_;
print "ref1 : @$ref1\n";
print "ref2 : @$ref2\n";
}
[ 実行結果 ]
> perl t_func.pl
ref1 : 1 2 3
ref2 : 4 5 6
\ 演算子でリファレンスを、& 演算子でデリファレンスを作成できます。
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_funcref.pl
# Function : make reference of function
#-----------------------------------------------------
use strict;
my $sub_ref = \& func;
&{$sub_ref}('one_way');
exit(0);
sub func {
print "$_[0]\n";
}
[ 実行結果 ]
perl t_funcref.pl
one_way
![]() |
![]() |
| 演算子 | 説明 | 例 |
|---|---|---|
| lc(STRING) | 小文字変換 | $lstr = lc("AAAAA"); |
| uc(STRING) | 大文字変換 | $ustr = uc("aaaaa"); |
| chomp([STRING]) | 文字列の最後の1文字を削除する | chomp(); |
| length([STRING]) | 文字列長をバイト単位で返す | $len = length($_); |
| substr(STRING,OFFSET[,LENGTH]) | 文字列の OFFSET 目から LENGTH バイトの文字列を返す | $sub = substr($str,3); |
| index(STRING,SUBSTR[,OFFSET]) rindex(STRING,SUBSTR[,OFFSET]) |
文字列の SUBSTR の位置を返す。ない場合は -1 | $pos = index($str,"="); |
| sprintf(FORMAT_STRING,arg1,arg2,...) | 指定された書式の文字列をかえす | $str = sprintf("%4d: %s\n",lno,line); |
![]() |
![]() |
| 演算子 | 説明と例 |
|---|---|
| shift[(@ARRAY)] | 配列 ARRAY の最初の要素を取り出し、全体に1つずれます
省略時は ARGV に対して演算を実行します
@array = ('aaa','bbb','ccc');
$first = shift(@array);
print "shift : shift=",$first," arry=",@array,"\n";
|
| unshift(@ARRAY,LIST) | 配列 ARRAY の最初に要素(複数可)を追加します$no = unshift(@array,'111','222'); print "unshift : no=",$no," arry=",@array,"\n"; |
| pop(@ARRAY) | 配列 ARRAY の最後の要素を取り出します$stack = pop(@array); print "pop : pop=",$stack," arry=",@array,"\n"; |
| push(@ARRAY,LIST) | 配列 ARRAY の最後に要素(複数可)を追加します$no = push(@array,'ddd','eee'); print "push : no=",$no," arry=",@array,"\n"; |
| splice(@ARRAY,OFFSET [,LENGTH[,LIST]]) |
配列 ARRAY の OFFSET 番目から LENGTH 個 LIST で置換し、置換部を返します
@mem = splice(@array,3);
print "splice : rep=",@mem," arry=",@array,"\n";
@mem = splice(@array,1,3,('AAAA','bbbb','CCCC'));
print "splice : rep=",@mem," arry=",@array,"\n";
|
| sort([SUBROUTINE,] LIST) | LIST の要素をソートし、結果のリストを返します@sort = sort(@array); print "sort : sort=",@sort," arry=",@array,"\n"; |
| reverse(LIST) | LIST の要素を逆順にし、結果のリストを返します@reverse = reverse(@array); print "reverse : reverse=",@reverse," arry=",@array,"\n"; |
| join(DELIM,LIST) | LIST を DELIM で結合した結果のリストを返します
$join = join(':',@array);
print "join : join=",$join," arry=",@array,"\n";
|
| split(/PATTERN/ [,STRING[,LIMIT]]) |
PATTERN に合致する文字列を区切り STRING でリストに分解します@split = split(/:/,$join); print "split : split=",@split," string=",$join,"\n"; |
| grep(EXPR,LIST) | LIST の要素で EXPR(正規表現可)を満たすものを返します@grep = grep(/[A-Z]+/,@array); print "grep : grep=",@grep," arry=",@array,"\n"; |
![]() |
![]() |
| 演算子 | 説明 | 例 |
|---|---|---|
| keys(%ARRAY) | 連想配列のキーの集合を配列で返す | @key_ele = keys(%ARRAY); |
| values(%ARRAY) | 連想配列の値の集合を配列で返す | @val_ele = values(%ARRAY); |
| each(%ARRAY) | 連想配列のキーと内容を返す。なくなったら偽を返す | while (($word,$count) = each %ARRAY) {
print "\t$word\t$count\n";
} |
| scalar(keys %ARRAY) | 連想配列の指定されたキーの集合の数を返す | $eleno = scalar(keys %ARRAY); |
| delete $ARRAY{'first'}; | 連想配列の指定されたキーと値を削除する | delete(%ARRAY{'first'}); |
| exists $ARRAY{'first'}; | 連想配列の指定されたキー値の存在を調べる | $status = exists(%ARRAY{'first'}); |
![]() |
![]() |
| 関数 | 意 味 | 例 |
|---|---|---|
open(ファイル識別子, "ファイル名");< : read from > : write to >& : write to (STDOUT/STDERR) >> : append to write to |
ファイルをオープンする | open(FIN,"< aaa.out"); while (<FIN>) print $_; } |
| close(ファイル識別子); | ファイルをクローズする | close(FOUT); |
| print ファイル識別子, "文字列"; | 文字列をファイルに書く | print FOUT,"$string \n"; |
| stat (ファイル名); | ファイルの属性を知る 添え字 得られる情報 [ 0 ] ファイルシステムのデバイス情報 [ 1 ] |ノード番号 [ 2 ] ファイルモード(パーミッション等) [ 3 ] 対象ファイルのリンク数 [ 4 ] 対象ファイル所有者のユーザー ID [ 5 ] 対象ファイルグループのグループ ID [ 6 ] デバイス識別子 [ 7 ] ファイルサイズ(バイト数) [ 8 ] 最終アクセス時間 [ 9 ] 最終変更時間 [ 10 ] 最終|ノード変更時間 [ 11 ] 最適ブロックサイズ [ 12 ] 割り当てられているブロック数 |
($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks ) = stat ($filename); |
| 関数 | 意 味 | 例 |
|---|---|---|
| system(コマンド); | コマンドを実行する | system('ls'); |
| exec(コマンド); | コマンドを perl プログラムと置換して実行する | exec('ls'); |
eval(STRING) は、実行時に生成された STRING を perl の文として実行する関数です。
$@ は eval で実行した結果、致命的なエラーが発生した場合はエラーメッセージが、
成功した場合は空文字がセットされます。
ただし eval で指定した文字列は毎回コンパイルされるので遅くなる。
$_ = '\n';
while (<>) {
$a = eval($_);
print $a unless ($@);
}
| 関数 | 意 味 | 例 |
|---|---|---|
| die "メッセージ"; | メッセージとともに実行を終わる | die "Cannot open data file.\n"; |
| warn "メッセージ"; | メッセージを出す | warn "Invalid data\n"; |
![]() |
![]() |
| 文字 | 意 味 | 例 |
|---|---|---|
| @ | 配列変数 | @array |
| % | 連想配列変数:ハッシュ変数 | %array |
| $ | スカラ変数(普通の変数) | $num |
| \ | 変数のリファレンスをとる(アドレス) | $addr = \@aaa; |
| 引用符 | 意 味 | 例 |
|---|---|---|
| ' | この引用符で囲まれた文字列中のメタ文字は無視します | $var1 = '$ARGS'; # $ARGS そのもの |
| " | この引用符で囲まれた文字列中の $ ` \ 以外のメタ文字は無視します | $var1 = "$ARGS"; # $ARGS の値 |
| qr() | 括弧内の文字列は quoted regular expression として扱える | $var1 =~ qr([a-zA-Z0-9]+); # 英数にマッチするもの |
| qq() | 括弧内の文字列は quoted string として扱える | @var1 = qq(It's a beautiful world); |
| qw() | 括弧内の文字列は quoted word として扱える | qw| .......| qw\ .......\ |
| メタ文字 | 説明 |
|---|---|
| \n | 改行(UNIXではLF) |
| \r | キャリッジリターン(UNIXではCR) |
| \t | タブ |
| \f | 改ページ文字 |
| \b | バックスペース |
| \a | アラート/ベル |
| \e | エスケープ文字(ESC) |
| \0数字 | 8進数でビットの並びを指定(したその文字) |
| \x数字 | 16進数で指定 |
| \cC | コントロールC |
| \x{数字} | UNICODEの文字 |
| \u | 次の1文字を大文字に変換 |
| \l | 次の1文字を小文字に変換 |
| \U | これ以降の全ての文字を大文字に変換 |
| \L | これ以降の全ての文字を小文字に変換 |
| \Q | これ以降の、全ての半角英数字以外の前に逆スラッシュを挿入 |
| \E | \U \L \Q の効果をここで打ち消す |
![]() |
![]() |
ファイルハンドルは、 perl プログラムが他のファイルを参照するときに使う名前のことで、 独自の名前空間にて管理されている。 通常大文字で記述します。 perl では STDIN、STDOUT、STDERR をあらかじめオープンしています。 標準装備以外のファイルハンドルを使う場合、 open 関数を使ってオープンする必要があります。
open(IN,"ファイル") || die("Open error"); [read]
open(OUT,">ファイル") || die("Open error"); [write]
open(APP,">>ファイル") || die("Open error"); [append]
if (! open(APP,">>ファイル")) { exit(1);} [append]
open ( filehandle, "command |" ); コマンドの出力を読み込む
open ( filehandle, "| command" ); 出力をコマンドに送る
while(<IN>) {
chomp;
print $_;
}
![]() |
![]() |
ファイルハンドルには、いろいろな使い方があります。
このプログラムは、カレントディレクトリの ls の結果をソートして印刷します。
#!/usr/local/bin/perl -w #----------------------------------------------------- # FileName : t_sort.pl #----------------------------------------------------- open(SORTED,"ls|sort|uniq|") || die "ERROR: sort command\n"; while () { chomp(); print "$_ "; } close(SORTED);
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_cmd.pl
# Usage : perl t_cmd.pl lc
#-----------------------------------------------------
use strict;
my %command;
my $cmdname;
my @answer;
$cmdname = $ARGV[0];
%command = (
'netstat_a' => 'netstat -a',
'lc' => 'ls -aCF',
'pse' => 'ps -ef ',
);
if (!(open (CMD,"$command{$cmdname} 2>&1 |"))) {
print ("error\n");
}
@answer = ;
print @answer;
close(CMD);
[ 実行結果 ]
ozzy-4 07/07 11:26am] perl t_cmd.pl lc
./ prep* t_ary.pl t_sub.pl
../ ps.pl t_assary.pl t_time.pl
ABC/ save.cgi t_cmd.pl t_tstdata.pl
LOCK search.cgi t_comma.pl t_var.pl
RESULT sep.pl t_data.pl t_while.pl
bb sep.pl.old t_for.pl tbl.pl
book/ sep_tcp.pl t_foreach.pl text/
プログラムの中に直接ドキュメントを書く方法をヒアドキュメントといいます。 もちろんその中に変数名があると、値に置き換わります。
print <<_END_OF_DOC ここから _END_OF_DOC までがドキュメントです data1 data2 $addr $addr の値が印刷されます _END_OF_DOC 必ず行頭でなければなりません
![]() |
![]() |
h2xs -Xn モジュール名 pl2pm perl プログラム名 これで新規のディレクトリ(モジュール名)以下にスケルトンが作られます。 実際のモジュール名は、モジュール名.pm です。
package 文は、名前空間を宣言します。 従って以降の名前空間は main ではなく、package で指定した名前となります。
package cgi_util; <== モジュール名でファイルをつくる(cgi_util.pm)
@EXPORT = qw(file_mode); <== 外部参照できるようにする
#------------------------------------------------
# Function : pickup 1st char of directory info
# Return : mode
# mode d: dir
# -: file
# l: symbolic link
#------------------------------------------------
sub file_mode {
local ($lmode)=$_[0];
local ($first);
$first = substr($lmode,0,1);
$first;
}
1; <== use で読めるようにする
use cgi_util; <== include する $lmode = file_mode($dir_info); <== call
perl で FTP を行うには、FTP.pm モジュールを使うと簡単に実現できます。
use Net::FTP; # FTP include FTP モジュール
my ($ftp,$status,@list);
my ($hostName,$userName,$passWord,$srcDir,$base_dir,$dir_base);
my $PRG_NAME = 'unix_load.pl';
# connect
$ftp = Net::FTP->new($hostName, Debug => 0); connect
&err_msg('ERROR : connect',$hostName,$PRG_NAME) unless ($ftp);
$status = $ftp->login($userName, $passWord); logon
&err_msg('ERROR : logon ',$userName,$PRG_NAME) if ($status == 0);
# chdir to HOME
$status = $ftp->cwd($srcDir); cwd
&err_msg('ERROR : non exists ',$srcDir,$PRG_NAME) if ($status == 0);
# get dir informations from remote host
$base_dir = $ftp->pwd(); pwd
@list = $ftp->ls("-l $dir_base"); ls -l
# disconnect
$ftp->quit; disconnect
![]() |
![]() |
クラスはパッケージですから、package 文を使ってクラスを宣言します。
package クラス名; コンストラクタの作成
コンストラクタは、新しいオブジェクトを作成しそのリファレンスを返すメソッドです。 クラス作成の順番は次のようになります。
package Class;
sub new {
my $class = shift;
....
}
オブジェクトを用意します。 ここでは、無名ハッシュのリファレンスを作成していますが、ハッシュ以外にもスカラや配列を返しても問題ありません。
# 無名ハッシュのリファレンスを作成
my $self = {};
ここでオブジェクト属性をセットしておくこともできます。
my $self = { x=10, y=20 };
あとは bless 関数に作成したオブジェクトとクラス名を渡して終わりです。
# bless したオブジェクトリファレンスを返す
return bless $self, $class;
bless 関数の引数は、リファレンスとパッケージ名です。 第1引数で与えられたリファレンスが指すオブジェクトは、 第2引数で指定したクラスに所属します。 第2引数のパッケージ名はオプションを省略すると現在のパッケージ名を引数とします。
my $self = {};
bless $self, $class;
bless した変数はクラスのオブジェクトに属することになるので、 普通の変数と区別するためにインスタンスと呼ばれます。 ここでは単純に、「bless の第1引数としてw定した変数がインスタンス」とおぼえておいてください。
package Class;
# コンストラクタ定義
sub new {
my $class= shift;
bless { x => shift }, $class;
}
# デストラクタ定義
sub DESTROY{
my $self = shift;
print "DESTROY > $self->{x}", "\n";
}
#------------------------------------------#
package main;
$a = new Class( '001' );
{
my $b = new Class( '002' );
}
# $b がスコープ外となり、'002' のオブジェクトが破棄される
# '001' は上書きされ、そのオブジェクトが破棄される
$a = new Class( '003' );
出力結果は次のようになります。
DESTROY > 002 # スコープの外に出た瞬間にDESTROYが呼ばれる
DESTROY > 001 # 上書きされた瞬間にDESTROYが呼ばれる
DESTROY > 003 # スクリプト終了直前にDESTROYが呼ばれる
オブジェクト指向の「継承」を使えば、元のクラスの資源をもとに、 新しいクラスを簡単に作成することができます。 オブジェクト指向では、元になるクラスをスーパークラス、 それから派生したクラスをサブクラスと呼びます。
既存のクラスを継承してサブクラスを定義するには、 サブクラス内で @ISA にスーパークラスの名前をセットします。
ClassA.pm という名前でスーパークラスを作成しましょう。
# ClassA を宣言(ClassB のスーパークラスになります)
package ClassA;
# コンストラクタの作成
sub new {
my $class = shift;
my $self = { x => 10 };
bless $self,$class;
}
# メソッドの作成
sub print_x{
my $self = shift;
print $self->{x}, "\n";
}
1
次に、 ClassB.pm という名前でサブクラスを作成します。
# ClassB を宣言
package ClassB ;
# パッケージAの使用を宣言
use ClassA;
# @ISAにスーパークラスの名前「A」を設定
# これによってクラスBはクラスAを継承する
@ISA = qw ( ClassA );
# ClassB のコンストラクタ
sub new {
my $class = shift;
# ClassA のコンストラクタを呼び出す
my $self = new ClassA;
return bless $self;
}
1
これだけで継承が終わりました。 上記のクラスB は、クラスA のメソッドを全て受け継いでいます。
それでは、ClassB のコンストラクタに注目してください。 クラスに属したオブジェクトの作成で、ClassA のコンストラクタを呼び出しています。 ClassA から返されたオブジェクトリファレンスをそのまま ClassB のインスタンス変数として bless しています。 これで、ClassA のメソッド、インスタンス変数がすべてアクセス可能になりました。
ClassB を呼び出し、ClassA の print_x メソッドを利用するには次のようになります。
use ClassB; my $obj = new ClassB; # メソッドの読み出し $obj->print_x;
呼び出し側では、print_x メソッドが ClassA と ClassB のどちらかで定義されているかを気にする必要はありません。ただ呼び出すだけです。
スーパークラスのメソッドと同名のメソッドを定義することを、 「オーバーロード」と呼びます。 変数に新しい値を代入するのと同じように、スーパークラスのメソッドを上書きできます。
以下の例は、スーパークラスのメソッドをオーバライドし、 オーバライドされた後でそのメソッドを呼び出しています。
#--------------------------------------#
# スーパークラスを定義
package Unix;
sub print_x { print "UNIX! \n" }
#--------------------------------------#
# サブクラスを定義
package Linux;
@ISA = qw( Unix );
sub new { bless {} }
sub print_x { print "LINUX! \n" }
#--------------------------------------#
package main;
my $obj = new Linux;
$obj->print_x;
サブクラスでオーバーロードされた元のメソッドは、 スーパークラスを表す SUPER という擬似クラスで呼び出せます。
# スーパークラスの new メソッド呼び出し my $obj = $class->SUPER::new( $x, $y );
これでスーパークラスのコンストラクタ new メソッドが実行されます。 スーパークラスのメソッドを呼び出すには、クラス名::メソッド名とします。 モジュールからサブルーチンを参照する方法と同じ記法ですね。
配列@ISAには複数のクラス名を設定することが出来ます。 この場合、2個以上のクラスからメソッドを継承することになります。 これを多重継承といいます。
多重継承の場合、@ISAに設定されたスーパークラスを1つづつ順に並べて、 起動すべきメソッドを探します。
#--------------------------------------#
# スーパークラスを定義
package Unix;
sub unix { print "UNIX! \n" }
#--------------------------------------#
# サブクラスを定義
package Linux;
@ISA = qw( Unix );
sub linux { print "Linux! \n" }
#--------------------------------------#
package Mac;
sub mac { print "mac! \n" }
#--------------------------------------#
package Foo;
@ISA = qw( Google Infoseek );
@Foo::Inherit::ISA = @ISA; # オーバライドされたメソッドのアクセス
sub new { bless [] }
sub goo {
my $self = shift;
$self->Foo::Inherit::goo();
}
sub google {
my $self = shift;
$self->Foo::Inherit::google();
}
sub infoseek {
my $self = shift;
$self->Foo::Inherit::goo();
}
sub grr { print "grumble\n" }
#--------------------------------------#
package main;
$foo = new Foo;
$foo->goo;
$foo->google;
$foo->grr;
![]() |
![]() |
| オプション | 機 能 |
|---|---|
| -n | whicle(<>) { } 内で実行 |
| -p | 各ループの最後に print; を実行する。通常 -n と併用する |
| -w | 識別子について様々な警告を出す。 |
| -c | スクリプトの文法をチェックし、実行せずに終了する。 |
| -d | perl デバッガのもとでスクリプトを実行する。 |
| -P | C プリプロセッサを通す。つまり、#include や #define が使える。 |
| -I | require のファイルまたは -P の include の検索するディレクトリを指定 |
| -v | バージョン表示 |
![]() |
![]() |
| 項目 | 説 明 |
|---|---|
| 局所変数 | これまでの local に加えて、 my ができました。 |
| eval | これまでは eval の引数は文字列で、 プログラムを実行時に作る目的で使われましたが、 これに加えて、引数にブロックを取るものができました。 これは、例外処理に役立ちます。 |
| サブルーチン呼び出し | 呼び出すところより前で宣言されているサブルーチンを呼び出す時は、 サブルーチン名の前に & をつけなくてよくなりました。 これにより、ユーザが定義した関数や、ライブラリの関数も、 組み込み関数としなくてよくなりました。 |
| サブルーチンの引数の型宣言 | 引数の型を宣言することで、ミスがチェックできるようになりました。 また、コンテキストを特定することもできるようになりました。 |
| BEGIN, END | コンパイル時に実行する BEGIN と、 終了時に実行する END という 特別なサブルーチンが用意されました。 これは、 -n スイッチなどを使った一行プログラムで、 AWK の BEGIN, END と同じ役割をするので特に便利です。 |
| 参照 | 参照ができました。 C でいうところの、「ポインタ」のようなものです。 これを使って、多次元配列を始めとする 複雑なデータ構造が作りやすくなりました。 |
| モジュール | ライブラリはモジュール化されました。 さまざまなモジュールが用意されています。 |
| オブジェクト指向 | モジュールを使って、オブジェクト指向プログラミングが実現されました。 |
| 正規表現の拡張 | 正規表現中にコメントが書けるようになりました。 |
| 表記法 | 連想配列のキーと値の対応を示す => や、 文字列のリストを表現する qw など、新たな表記法が加わりました。 |
| 組み込み関数の改良 | chop の改良版である chomp など、新たに組み込み関数が追加されたり、 機能が変更されたりしています。 |
![]() |
![]() |
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_time.pl
#-----------------------------------------------------
use strict;
use POSIX;
my $date;
$date = & mk_date();
print "$date\n";
exit(0);
#------------------------------------------------
# Function : make current date string
# Return : date string
#------------------------------------------------
sub mk_date {
my ($time_t,$mday,$hour,$min,$sec,$mon,$year,$wday,$yday,$isdst,$buf) ;
$time_t = time();
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time_t);
$year += 1900;
$mon += 1;
$buf = sprintf("%4d/%02d/%02d %02d:%02d:%02d",
$year,$mon,$mday,$hour,$min,$sec);
return $buf;
}
[ 実行結果 ]
2004/07/07 13:51:37
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : pk_html_h.pl
# Function : convert <h1> to <H1>
#-----------------------------------------------------
use strict;
my $lno=0;
while (<>) {
$lno ++;
chomp($_);
if (m|(<h[1-6]>)|) {
s|||g;
s| | |g;
print "$lno] $_ \n";
}
}
exit(0);
[ 実行結果 ]
> cat namazu.html | perl pk_html_h.pl
8] <H1> namazu </H1>
451] <H5>必要条件 </H5>
468] <H5>起動と停止 </H5>
483] <H5>必要条件 </H5>
500] <H5>起動と停止 </H5>
509] <H5>必要条件 </H5>
525] <H5>起動と停止 </H5>
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_cmd.pl
# Usage : perl t_cmd.pl lc
#-----------------------------------------------------
use strict;
my %command;
my $cmdname;
my @answer;
$cmdname = $ARGV[0];
%command = (
'netstat_a' => 'netstat -a',
'lc' => 'ls -aCF',
'pse' => 'ps -ef ',
);
if (!(open (CMD,"$command{$cmdname} 2>&1 |"))) {
print ("error\n");
}
@answer = ;
print @answer;
close(CMD);
exit(0);
[ 実行結果 ]
> perl t_cmd.pl lc
./ prep* t_ary.pl t_sort2.pl
../ ps.pl t_assary.pl t_sub.pl
ABC/ save.cgi t_cmd.pl t_time.pl
LOCK search.cgi t_comma.pl t_tstdata.pl
RESULT sep.pl t_data.pl t_var.pl
#!/usr/local/bin/perl -w オプション use strict; use diagnostics; use constant DEBUG => 1;
use Data::Dumper; print Dumper \%list;
デバッガのコマンドは以下のとおりです。
| 機能 | コマンド | 内容 |
|---|---|---|
| ブレイク | T | スタック・トレースを行います |
| L | ブレイク・ポイントまたはアクションを持つ行を表示します | |
| S | すべてのサブルーチン名をリスト表示します | |
| t | トレース・モードを切り替えます。 このコマンドは、トグルになっており、現在 on なら off に、 現在 off なら on に切り替えます |
|
| b line [condition] | ブレイク・ポイントを設定します。 line を省略すると、現在行のブレイク・ポイントを設定します。 condition を指定すると、condition が真のとき実行を中断します。 記述例 : b 23 $x > 30 |
|
| b subname [condition] | サブルーチンの最初の実行文に、ブレイク・ポイントを設定します | |
| d line | 指定した行のブレイク・ポイントを削除します。 line を省略すると、現在行のブレイク・ポイントを削除します |
|
| D | すべてのブレイク・ポイントを削除します | |
| 実行 | s | シングル・ステップ。別の実行文に到達するまで実行します |
| n | 次の実行文までを、サブルーチンを含めて実行します | |
| f | 現在のサブルーチンを終えるところまで実行します | |
| c c line |
次のブレーク・ポイントまで実行します。 指定した行までを実行します |
|
| <CR> | 最後に実行した n コマンドまたは s コマンドをリピートします | |
| ! number | デバッグ・コマンドを再実行します。 number を省略すると、直前のコマンドを実行します |
|
| ! -number | number で指定した数だけ前のコマンドを実行します | |
| q or ^D | デバッガを終了します | |
| command | >指定した command を、Perl の文として実行します。 文末のセミコロンは省略できます p expr print DB::OUT expr と同じです |
|
| 値表示 | p $symbols | 指定した変数を表示します。 |
| V package [symbols] | 指定したパッケージ内のすべての変数を表示します。 symbol は $ などを付けず、名前だけを指定します。 |
|
| X [symbols] | 現在のパッケージ内のすべての変数を表示します。 symbol は $ などを付けず、名前だけを指定します。 |
|
| リスト | l | 次の1画面をリスト表示します |
| l min+incr | min 行から incr+1 行をリスト表示します。min を省略すると、 最後にリスト表示を実行した最後の行から表示します。 incr を省略すると、前回実行したときの incr が使われます |
|
| l min-max | 指定した範囲をリスト表示します。 | |
| l line | 指定した行をリスト表示します | |
| l subname | 指定したサブルーチンをリスト表示します。 長いサブルーチンの場合は、最初の1画面分を表示します。 続きは l コマンドで表示されます。 |
|
| - | 前の1画面をリスト表示します | |
| w line | 指定した行の付近をリスト表示します | |
| H -number | 最近実行したコマンドで、number で指定した数のコマンドを表示します。 2文字以上のコマンドだけが表示されます。 number を省略すると、すべてを表示します。 |
|
| 検索 | /pattern/ | ソース・コード上で、正規表現 pattarn を検索します。 最後の / は省略できます |
| ?pattern? | ソース・コード上で、正規表現 pattarn を逆方向に検索します。 最後の ? は省略できます。 |
|
| コマンド | a line command | 指定した行にアクションを設定します。 複数行の command を指定する場合は、バックスラッシュと改行を使います。 command はデバッガのコマンドではなく、Perl のコマンドを指定します |
| < command | デバッガがプロンプトを表示する前に実行するアクションを指定します。 このアクションは、毎回実行されます。 複数行の comannd を指定する場合は、バックスラッシュと改行を使います |
|
| > command | プログラムの実行に戻るコマンドを入力したとき、 デバッガがプロンプトを表示した後に実行するアクションを指定します。 このアクションは、毎回実行されます。 複数行の command を指定する場合は、バックスラッシュと改行を使います。 |
|
| A | すべてのアクションを削除します | |
| h | ヘルプ・メッセージを表示します。 |
AUTOLOAD BEGIN CHECK CORE DATA DESTORY END GLOBAL INIT EQ,GE,GT,LE,LT,NE STDIN,STDOUT,STDERR
perldoc perl man perldebug
$_ はグローバル変数なので、再帰呼び出しされるサブルーチンでは必ず local 宣言しないと、値が変えられてしまう可能性があります。 local 宣言すると、宣言したところで、局所的な変数扱いとなりますが、 そこを出ると、以前の値がセットされます。 local $_;
$i の実行後の値は初期値に再設定され、10 ではありません。
print qq(string "string" 'string' string);
my:
宣言スコープ内側に完全にプライベート。
これをレキシカルスコープという。
静的スコープ
perl 5 から導入された
local:
宣言スコープ内から呼ばれる他の別空間スコープ(関数内)からもアクセス可。
動的スコープ
システム予約変数を局所的に使いたい時使用する。
local は局所変数ではなく、単に宣言したスコープでは別の値を持つように
しているだけです。
#!/usr/local/bin/perl -w
#-----------------------------------------------------
# FileName : t_my_local.pl
# Function : test of my and local
#-----------------------------------------------------
$a = "global"; test();
{
local $a="local"; test();
}
{
my $a="my";test();
}
exit(0);
sub test {
print "a=$a \n";
}
[ 実行結果 ]
> perl t_my_local.pl
a=global
a=local
a=global
配列のリファレンス(アドレス)を渡すことで、実現できます。
my (@ary1,@ary2);
&sub1(\@ary1,\@ary2); 配列のリファレンスを渡す
sub sub1 {
my ($parm1,$parm2) = @_ ; リファレンスを変数に設定する
print "@$parm1\n"; リファレンスから実体を参照する
print "@$parm2\n"; リファレンスから実体を参照する
}
| 略語 | 説明 |
|---|---|
| CGI | Common Gateway Inteface |
| CPAN | Comprehensive Perl Archive Network |
| POD | Plain Old Document |
| SSI | Server Side Include |
| 名前 | 出版社 | 値段 |
|---|---|---|
| 新 perl の国へようこそ | サイエンス社 | 3200 |
| プログラミング perl マスターコース | ピアソンエデュケーション | 3400 |
| perl デバッグ | ピアソンエデュケーション | 2600 |
| perl & CGI | ピアソンエデュケーション | 4600 |
| CGI プログラミング | オーム社 | 2600 |
| CGI 基礎講座 | 翔詠社 | 2800 |
| perl | マニュアル | ワンライナー | perl CGI 入門 | プログラミング講座 |
|---|---|---|---|---|
| perl 情報 | perl バイブル | |||
| モジュール | マニュアル | FreePerl.com | Jcode.pl | |
| ユーザグループ | 東京 | CGI 関連 |
| 用語 | 意味 |
|---|---|
| キャプチャ | 正規表現でマッチしたものを特殊変数 $1,$2,... に格納すること |
| クロージャ | 無名サブルーチンへのリファレンス |
| リスト | スカラーデータに順序を付けて並べたもの |
| スライス | 同一の配列に含まれる複数の要素にアクセスすること |
![]() |
![]() |
#!/usr/local/bin/perl
<FORM ACTION=XXX.pl?arg1+arg2 METHOD=POST>
引数は %ENV{'QUERY_STRING'} に格納されます。
引数が日本語の場合、%ENV{'HTTP_ACCEPT_CHARSET'} で示されるコードになっています。
例えば、UNIX マシンで実行する perl を Windows 上に表示している場合、
SJIS に変換されていますので Jcode を使って EUC に変換します。
$cur_dir = Jcode::convert($query,'euc');
ただしブラウザにより動作が異なります。 IE の場合、日本語の変換が正しく行われない。 (回避策としては、encode する)
<FORM ACTION=XXX.pl METHOD=POST> <INPUT TYPE="checkbox" NAME="box" VALUE="UNIX" CHECKED >UNIX <INPUT TYPE="checkbox" NAME="box" VALUE="DOS" >DOS <INPUT TYPE="checkbox" NAME="box" VALUE="WiNNT" >WinNT <INPUT TYPE="checkbox" NAME="box" VALUE="LINUX" >LINUX <INPUT TYPE="submit" VALUE="実行"> 押してください </FORM>POST されたデータ長は %ENV{'CONTENT_LENGTH'} に格納されます。 これを STDIN から読み込みます。
ただし、この文字列はエンコードされていますので、 デコードする必要があります。
read(STDIN,$qstr,$ENV{'CONTENT_LENGTH'});
($title,$linkname) = split(/=/,$qstr);
$linkname =~ s/%([a-fA-F0-9][[a-fA-F0-9])/pack("c",hex($1))/ge ;
https の場合、REQUEST_METHOD の POST が GET になってしまい、 %ENV{'QUERY_STRING'} に格納されてしまうことがあります。
CGI の場合、環境変数は %ENV で perl プログラムに渡されます。 環境変数とその値を列挙すると、概ね以下のとおりです。
ブラウザ情報は HTTP_USER_AGENT = Mozilla/4.75 [ja] (Windows NT 5.0; U) にあります。
SERVER_SOFTWARE = Apache/1.3.6 (Unix) GATEWAY_INTERFACE = CGI/1.1 DOCUMENT_ROOT = /home06/websrv REMOTE_ADDR = 172.30.33.68 SERVER_PROTOCOL = HTTP/1.0 SERVER_SIGNATURE = Apache/1.3.6 Server at ozzy.open.enicom.co.jp Port 8080 REQUEST_METHOD = POST HTTP_REFERER = http://bach.it.ns-sol.co.jp:8080/hp/taka/HP/html_CGI.html QUERY_STRING = 日本語+システム HTTP_USER_AGENT = Mozilla/4.75 [ja] (Windows NT 5.0; U) PATH = /usr/sbin:/usr/bin:/usr/ccs/bin:/usr/proc/bin:/usr/local/bin:/usr/local/sbin TZ = Japan HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */* REMOTE_PORT = 30728 HTTP_ACCEPT_LANGUAGE = ja HTTP_CACHE_CONTROL = max-stale=0 SCRIPT_NAME = /cgi-bin/tst.pl HTTP_ACCEPT_ENCODING = gzip SCRIPT_FILENAME = /home06/taka/cgi-bin/tst.pl SERVER_NAME = ozzy.open.enicom.co.jp REQUEST_URI = /cgi-bin/tst.pl?日本語+システム HTTP_ACCEPT_CHARSET = Shift_JIS,*,utf-8 SERVER_PORT = 8080 CONTENT_TYPE = multipart/form-data; boundary=---------------------------26972134376704 CONTENT_LENGTH = 47 HTTP_HOST = ozzy.it.ns-sol.co.jp:8080 SERVER_ADMIN = websrv@ozzy.open.enicom.co.jp
| ブラウザ | HTTP_USER_AGENT/HTTP_ACCEPT_CHARSET |
|---|---|
| Netscape 4.7 | Mozilla/4.75 [ja] (Windows NT 5.0; U) Shift_JIS,*,utf-8 |
| MSIE 6.0 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) |
| Mozilla 5.0 | Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7.1) Gecko/20040707 Shift_JIS,utf-8;q=0.7,*;q=0.7 |
| Opera 7.23 | Mozilla/5.0 (Windows NT 5.0; U) Opera 7.23 [ja] shift_jis, utf-8, utf-16, iso-8859-1;q=0.6, *;q=0.1 |
内包される Mozilla のバージョンにより、日本語処理が異なり、 5.0 ja-JP であると、内部コードは EUC となります。
![]() |
![]() |
perldoc -f サブルーチン名 perl のサブルーチンの man を知る perldoc モジュール名 perl のモジュールの man を知る perldoc POSIX POSIX モジュールの説明 perldoc CGI CGI モジュールの説明 perldoc constant 定義済み定数の説明
![]() |
![]() |