最終更新 2024.04.01
Perl表技集 Perl基礎入門
ファイルの先頭に use strict; と書くと、そのファイル中のメイン関数(関数宣言なしに 書き始める部分)、サブルーチン全てに変数宣言が必要となる。 変数宣言は my $a; my ($a,$b,$c,@array); のように行う。配列変数は @ をつける。
メイン関数の中で宣言した変数はグローバル変数となる。
break : last continue : next
open(FP,"> file"); print FP "$moji\n"; printf FP ("%4d \n",$i); close(FP); open(FP,"<&STDIN"); open(FP,"< file"); $moji = <FP>; close(FP); open(FP,">&STDERR"); $iret = open(FP,"< file"); if ( $iret == FALSE ){ print STDERR "cannot open file\n"; exit 1; } 成功したとき : 1 失敗したとき : 空白 open(FP,"< $fname") || die "cannot open file $fname\n"; ファイルのロック open(FP,"> filename"); flock(FP,2); # ロック print FP,"...."; flock(FP,8); # 解除 close(FP); 読み書きモードの使い方 open(FP,"+< filename"); $dat = <FP>; 読み込み truncate(FP,0); # ファイルサイズを 0 にする # これを怠ると seek の後に書き込んだサイズが元のファイルより # 小さいとき、元のファイルの後半が残る seek(FP,0,0); # 読み取りポインタをファイル先頭に print FP "data\n"; close(FP);
unlink ("fname","fname2","fname3");
print "i = ",$i,"\n"; basic と同じ構文 print "i = $i \n"; $i は " " の内側にも書ける print "\"i\" = 1\n"; エスケープシーケンス printf("a = %10.5lf \n",$a); C と同じように書いても良い $moji = sprintf("a = %10.5lf ",$a); sprintf は引数の書き方が少し違う $moji = sprintf("%20s ",$str); 20 文字右つめ $moji = sprintf("%-20s ",$str); 20 文字左つめ print FP "i = $i \n"; ファイルへの入出力 printf FP ("a = %10.5lf ",$a); print @list; 隙間なく並べる print "@list"; 要素ごとの間に空白を 1 つ入れる
$argc = @ARGV; 引数の個数を取得 $ARGV[0] 第一引数
<STDIN> <STDOUT> <STDERR>
$host = $ENV{'HOST'}; 環境変数はハッシュ変数 %ENV に入っている
値渡し &sub1($a,$b); sub sub1{ my($a2,$b2) = @_; <---- 引数は配列 @_ に格納される my($c); <---- $c はローカル変数 $b2 = 10; } ポインタ渡し ( ver.5.8 ではエラーになる。現在は使えないようだ) &sub2(*a,*b); sub sub2{ my(*c,*d) = @_; $c = 10; $d[0] = 1; $d[1] = 2; } ファイルハンドルの引数渡し &sub3(FP); sub sub3{ my($FP) = @_; $_ = <FP>; print "file : $_\n"; } サブルーチンからの戻り値 return 式; 複数の値を返すとき ($a,$b) = &sub4($a,$b) sub sub4{ my($c,$d) = @_; $c++; $d++; return ($c,$d); }
普通の配列 $array[0] = 'abc'; $array[1] = 'def'; foreach $item ( @array ){ } 連想配列 $a{'aa'} = 'xx'; $a{'ab'} = 'yy'; forcach $item ( keys %a ){ } forcach $item ( sort keys %a ){ }
$a = $b . $c; あるいは $a = "$b$c";
if ( $str =~ m/pattern/ ) m は省略可 if ( $str !~ m/pattern/ ) マッチングしない if ( $str =~ m/pattern/i ) i : 大文字小文字を無視 if ( $str eq $str2 ) (注)if ( 'aaa' == 'bbb' ) は真となるので注意。文字列の比較は eq を使う $str = "abc-def"; $str =~ m/(.*)-(.*)/; . は任意の1文字 * は 0 回以上の繰り返し () はグループを表す $1 $2 $3 ... の順番に入る print "$1 $2 \n"; $1 には abc $2 には def が入る $_ = "abc-def"; 上の例の省略形 m/(.*)-(.*)/; print "$1 $2 \n"; if ( $str =~ m/^\s*$/ ) 空行とのマッチング $str の最後が "\n" があっても上の式はマッチングする。 文字列の最後に "\n" があることが確実な場合は、 if ( $str =~ m/^\s*\n/ ) の方が分かりやすいかもしれない。
$str =~ s/previous/after/; 文字変数 $str を置換した結果が $str に入る s#previous#after#; / でなくてもよい。 s/previous/after/g; グローバルの略 マッチングするもの全て g を付けない時、最初にマッチしたものだけ置き換える s/previous/after/i; 大文字小文字区別せず
@list = split( ' ' , $str ); print "$list[0]\n";
$out = join(' ',@list); print "out\n";
行末に改行記号がある場合、切り落とす if ( $moji =~ m/\n$/ ){ chop($moji); } 長さの取得 $leng = length($a); Basic の MID$ $in = '123456789'; $a = substr($in,0,4); 最初から 4 文字取る $b = substr($in,4,5); 5 文字目から 5 文字取る $c = substr($in,3); 4 文字目から最後まで 結果 : $a = "1234" $b = "56789" $c = "456789"
$list[0] = "yabu"; 普通の配列 @list = ( 1 , 2 , 3 ); @list 配列全体 $size = @list 配列のサイズを得る $#list 配列の最後の要素番号 ( 要素は 0 から始まるので サイズ-1 が得られる ) push(@list,element) 配列の最後に要素を一つ加える $a = pop(@list) 配列の最後の要素を取り除き、その要素を返す unshift(@list,element) 配列の最初に要素を一つ加える $a = shift(@list) 配列の最初の要素を取り除き、その要素を返す。一つ前に詰められる $list{yabu} = "tetsuro"; 連想配列 %list 配列全体 引数処理の例 while($arg = shift(@ARGV)){ if ( $arg =~ m/^-/ ){ push(@options,$arg); } else { $fname = $arg; } }
perl には 2 次元配列はないが、$a[$i] までを変数名と 見なすことにより、以下のように C と全く同じ構文で、 2 次元配列を実現することが出来る。 for($i = 0; $i < 3; $i++){ for($j = 0; $j < 4; $j++){ $a[$i][$j] = $i * 10 + $j; } } for($i = 0; $i < 3; $i++){ for($j = 0; $j < 4; $j++){ printf("a[%d][%d] = %3d\n",$i,$j,$a[$i][$j]); } }
. 任意の1文字 x? 0 個あるいは 1 個の x x* 0 個以上の x x+ 1 個以上の x ^ 行の先頭 $ 行末 \s 空白文字 ( スペース、タブ、改行 ) \S 空白以外の文字 [0-9\-] 0 〜 9 の文字あるいは '-' 記号の固まり [^\"]+\" " 以外の文字の 1 つ以上の連続の後、" 文字
if ( 条件 || 条件 ) { } elsif ( 条件 && 条件 ) { } else { } $a == $b スカラ変数 $a != $b スカラ変数 $a eq $b 文字列 $a ne $b 文字列
$name{'yabu'} = "tetsuro"; $name{'sawa'} = "shinnosuke"; @list = sort keys %name; @list2 = sort values %name;
seek(FP,0,0); 第 2 引数の 0 バイト目、第 3 引数の 0 はファイル先頭から
$loc = tell FP; ファイルポインタの位置を得る $line = <FP>; 読み込む seek(FP,$loc,0); 先程の位置にもどす
eof(FP) が 1 のときファイルエンドを表す 例 下の二つの例は同じ while(1){ if ( eof(FP) == 1 ){ last; } $_ = <FP>; print; } while(<FP>){ print; } ( 注意 ) $_ = <FP> として最後の行を読み込んだ直後に eof(FP) は 1 になるので、 $_ = <FP>; if ( eof(FP) == 1 ){ last; } print; ではダメである。ここは C の fgets とは感覚が 異なるところであるから注意すること。
sub find_header { my(*FP,$header) = @_; seek(FP,0,0); $flag = 0; while(<FP>){ if ( m/^\s*$header/ ){ $flag = 1; last; } } if ( $flag == 0 ){ print "Cannot find header\n"; print "Exit.\n"; exit 1; } }
$hour = int( $min / 60 ); $min = $min % 60; また printf 文で実数型変数に対して %d を指定すると 小数部を切捨てて表示してくれる。
C 言語と同じ goto LABEL; LABEL:
opendir(DIR); @flist = readdir(DIR); closedir(DIR); chdir "/usr/local/bin";
if ( -d $fname ) $fname がディレクトリか否か if ( -f $fname ) $fname がファイルか否か if ( -l $fname ) $fname がシンボリックリンクか否か if ( -e $fname ) $fname が存在するか否か
$$ プロセス番号 $0 スクリプトファイルの名前(コマンドラインから打った値)
ctrl-C は 'INT' で表される。 SIGTERM でないのに注意! ( 例 ) $SIG{'INT'} = 'interrupt'; while(1){} sub interrupt { print "terminate\n"; exit 1; }
2種類の書き方がある。 --------------------- print <<END_MARK << と END_MARK の間に空白を入れてはならない ..... $a 変数も使える ..... END_MARK ; このセミコロンを忘れないように --------------------- --------------------- print << "END_MARK"; ..... $a ..... END_MARK ---------------------
@result = grep /文字/, @list @result = sort @list
@result = sort @list 普通のソート @result = sort {$a cmp $b} @list 上の内容を省略せずに書いたもの sort コマンドは $a, $b という一時変数 を使う。{ } の中が -1 なら $a を前に 並べ、1 なら $b を前に並べる。 $a cmp $b は文字変数 $a と $b の大小関係 を調べ、$a < $b なら -1 、$a == $b なら 0 $a > $b なら 1 を返す ただし、ここでの $a, $b はユーザーが 定義して使う変数 $a, $b とは別物である。 @result = sort {$b cmp $a} @list 逆順に並べる @result = sort {$a <=> $b} @list 数値を小さい順から並べる <=> は数値を比べる演算子 @result = sort {length($a) <=> length($b)} 文字長が短い順に並べる @result = sort {length($b) <=> length($a)} 文字長が長い順に並べる
@all = <>; 入力を行で区切って配列 @all に入れる
$| = 1;
shift @list; $list[0] <-- $list[1] $list[1] <-- $list[2] $list[2] <-- $list[3] unshift(@list,"top_item"); $list[0] <-- "top_item" $list[1] <-- $list[0] $list[2] <-- $list[1]
$msgfile = "/tmp/$$.tmp"; open(FP,"> $msgfile"); print FP "xxx\n"; print FP "$0 is executed normally.\n"; close(FP); system("/usr/bin/mail -s 'Report from $0' $ENV{USER} < $msgfile");
C と全く同じ 正常終了のとき返り値は 0 Command not found などで異常終了のとき返り値は -1 C-C で Abort したときの返り値は 2 65280 など。よくわからない。0 以外であることは間違いない。 エラー処理を付加した system 文の例 sub ysystem { my($command) = @_; if ( system($command) != 0 ){ print STDERR "error occurs in executing : $command\n"; exit 1; } }
sleep 1 1 秒待つ select(undef, undef, undef, 0.1) 0.1 秒待つ
# 以降はコメント __END__ 以降は無視される
$host = "denki.nara-edu.ac.jp"; ($hname,$aliases,$addrtyp,$length,@addrs) = gethostbyname($host); $addr = "192.168.107.50"; $host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2);
ディレクトリの新規作成の階層は 1 階層しかサポートしていない sub command{ my($command) = @_; print "$command\n"; system($command); } sub copy{ my($source_fname,$dist_fname) = @_; if ( ! -e $source_fname ){ print "file $source_fname does not exist.\n"; return; } @stat1 = stat($source_fname); # $stat1[9] に更新時刻が入る @stat2 = stat($dist_fname); # $stat2[9] に更新時刻が入る if ( $stat1[9] > $stat2[9] ){ $dist_fname =~ m/(^\S+)\/(\S+)$/; # ファイルが格納されるディレクトリ $dist_dir = $1; $dist_dir =~ m/(^\S+)\/(\S+)$/; $dist_dir1 = $1; # その親ディレクトリ $dist_dir2 = $2; # ディレクトリ名のみ if ( -e $dist_dir ){ } else { command("cd $dist_dir1; mkdir $dist_dir2"); } command("cp $source_fname $dist_fname"); } }
active perl 64bit 版 5.14 をインストールすると C:\Perl64 以下にインストールされる。path 変数の先頭に C:\perl64\site\bin; C:\perl64\bin が加えられ、拡張子 pl に C:\perl64\bin\perl.exe が結びつけられる。 pl ファイルをダブルクリックするとエラーが発生しても エラーメッセージを見ることが出来ない (DOS 窓らしきものが一瞬表示されるが視認できない)。 DOS 窓から ...>perl script-name.pl として実行するのが良さそうだ。
引用元 # ファイルの場合 @stat = stat($fname); @time = localtime($stat[9]); # 現在時刻 @time = localtime; # @time 配列の処理 @youbi = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = @time; $year += 1900; $mon += 1; $line = "$year/$mon/$mday $youbi[$wday] $hour:$min:$sec"; print "$line\n";