Perl覚書

 

文字列出力

print(“<文字列>”); 

print “”;     でもOK

 

計算

print(<数式>);

 

演算子

**      べき乗

例)

2**5 = 32;

$a += 5;

.       (ドット:文字列結合演算子

例)

$a = “hinako”;

$b = $a.” doi”;

print($b);      > hinako doi

.=      (ドットイコール:変数文字列結合演算子)

例)

$a = “yuiko”;

$a .=” doi”;

print($a);      > yuiko doi

 

変数

$x = 5;                 (変数$x5を代入)

print("x=$x\n");        (二重引用符は変数を展開する)

 

警告表示

Ø       perl –w <ファイル名>

で警告メッセージが表示される。

use strict;           (で、変数宣言を強制することも出来る)

 

初期化

undefは数値の場合は0,文字列の場合は””(空文字列)を表す。

defined()関数により、変数が初期化されているかどうかを判定することが可能。

 

分岐

if (<論理式> and,&&,or,|| <論理式>) {   #andorv5からの新機能

}

elsif (<論理式> and,&&,or,|| <論理式>) {

}

else {

}

 

unless (<論理式>) {     #論理式が偽なら実行

}

 

論理式

1 == 2          数字を比較

“a” eq “b”  文字列を比較(等しい)

“a” ne “b”  文字列を比較(等しくない)

0                      数字の0falseを表す(0以外はtrue

“”            空文字列“”はfalseを表す(“”以外はtrue)

注)実は、”0”falseと評価される。

 

繰り返し

while (<論理式>) {              #論理式がtrueの間繰り返す

        last    #繰り返しを脱出

        redo    #ループで繰り返しの最初に飛ぶ

        next    #ループで繰り返しの最後に飛ぶ

}

 

until (<論理式>) {              #論理式がfalseの間繰り返す

        last    #繰り返しを脱出

}

 

リストと配列

配列:$変数名[インデックス]     (宣言の必要なし)

$a[0] = 10;

 

リスト:複数の値を持ったデータ 

@a = (10, 11, 12);              @aは配列全体を表す)

配列を作成する一つの方法は、リストを作成すること。

($hinako, $yuiko) = (“hinako”, “yuiko”);

配列から新たに配列を作ることも可能。

@b = (@a, 21, 22, 23);

配列の代入先に、配列を指定することも出来るが、この場合左にある配列は可能な限り、勝手に大きさを増やして要素の代入を許す。

(@b, $c) = (@a, 99);

このとき、

$b[0]=10

$b[1]=11

$b[2]=12

$b[3]=99        #欲張って、これも取り込む

$c=undef        #よって、$cにはundefが残される

となる。

 

リストコンテキストとスカラーコンテキスト

式が複数の変数(配列など)を返す(とPerlが判断した)場合、リストが返される。

式が単一の変数(値など)を返す(とPerlが判断した)場合、スカラーが返される。

例)

@list = ($a, $b, $c, $d)       

このとき@listは、

$list[0]=$a

$list[1]=$b

$list[2]=$c

$list[3]=$d

を満たすリストとなる。

 

一方、

$n = @list + 0;

のとき、@listはリストの長さを表す値(スカラー)となる。

 

配列変数を(一まとめとして)表すには@aを用い、配列要素を表す場合には$aを用いる。

 

forでの配列操作:

for ($i = 0; $i <= $#a; $i++) {         $#aは配列変数@aの最後の要素のインデックスを表す)

        print($a[$i]." ");

}

for ($i = 0; $i <= @a; $i++) {          @aはこの場合スカラーコンテキストとして評価され、配列変数$a要素数を表す)

        print($a[$i]." ");

}

 

foreachでの配列操作:

foreach $var (@a) {                     $varには、配列変数@aの各要素が、先頭から末尾まで繰り返し代入される)

        print($var." ");

}

 

 

要素の交換

($b, $a) = ($a, $b);

 

配列の後ろからアクセス

$a[-1]  (配列の後ろから1番目の要素にアクセス)

$a[-2]  (配列の後ろから2番目の要素にアクセス)

 

スライスと範囲演算子

配列の一部を使ってリストを作ることが出来る

@a[2..3] (配列の3番目から4番目の要素のリスト)

 

スライスの添え字はリストコンテキストとして評価される。

Perlは関数を呼び出す際に、単数(スカラー)もしくは複数(リスト)の値を返して欲しいかを示す情報を関数に伝える。
この情報のことをコンテキストという。

 

配列操作関数

reverse():      配列の要素を逆順に配した配列を返す。

shift():        配列の先頭要素を削除し、その要素を返す。

unshift():      1引数で指定した配列の先頭に、第2引数以降の値を挿入する。挿入後の配列の要素数を返す。もともとの要素はその分後ろにずれる。

push():         1引数で指定した配列の末尾に、第2引数以降の値を追加する。挿入後の配列の要素数を返す。

pop():          配列の末尾要素を削除し、その要素を返す。

splice():       配列の任意の位置に要素を追加、削除する。

splice(ARRAY, OFFSET, LENGTH, EXPR……)
         ARRAY:   対象とする配列変数
         OFFSET:  操作する配列要素の場所(負数を指定した場合は、末尾からの位置)
         LENGTH:  削除する要素の数
         EXPR:    挿入する要素(複数可)

 

shift()の引数を省略すると、サブルーチンの中では@_が、それ以外の場所では@ARGVが対象になる。

@_はサブルーチンへの引数がセットされる特殊配列

@ARGVはスクリプトの起動時にコマンドラインに指定した引数がセットされる特殊配列

 

リストの末尾にリストを追加

@list = (@list, split(/\s/));

などとすれば、既存のリストにsplit関数の結果を追加することが出来る。ここで、

 

split関数:

split(/区切り文字のパターン/, 区切る対象, 区切る上限個数)

split(/区切り文字のパターン/, 区切る対象)                       #区切る個数の制限無し

split(/区切り文字のパターン/)                                   #$_を区切る

split                                                           #空白文字で区切る

 

スカラー関数

scalar():        配列をスカラーとして評価する関数。配列の要素数が得られる。

 

時刻関数

time():          現在の時刻を表す整数値返す。

localtime():     ローカル時刻を表すtm構造体に倣った、リストを返す。(引数が空の場合は、現在時刻)

gmtime():        GMT時刻を表すtm構造体に倣った、リストを返す。(引数が空の場合は、現在時刻)

$sec    秒(059
$min    分(059
$hour   時(023
$mday   日(131
$mon    月(011: 01月)
$year   年(西暦から1900を引いた値)
$wday   曜日(06: 0が日曜日)
$yday   年の始めから数えて何日目か(0365: 011日を表す)
$isdst  サマータイム期間中なら1、そうでなければ0
 
例)

$localtime = localtime();

print($localtime);
 

 

ハッシュ

%aで、キーと値を格納するハッシュ変数が宣言できる。

例)

%a =     (“dad”, “kotaro”,     #キーが”dad”で、値が”kotaro”

         “mam”, “akiko” );     #キーが”mam”で、値が”akiko”

まったく同じことが => 演算子を使っても書ける。

%a =     (“dad” => “kotaro”,   #キーが”dad”で、値が”kotaro”

         “mam”=> “akiko” );    #キーが”mam”で、値が”akiko”

 

それぞれの値にアクセスするには、

$a{“dad”}                        #とすると、”kotaro”を得る。

$a{“mam”}                        #とすると、”akiko”を得る。

 

keys()                             #ハッシュのキーを格納するリストを返す

each()                             #($key, $value)といったキー、値のペアであるリストを返す

values()                           #ハッシュの値を格納するリストを返す

などの関数が使える。

 

環境変数

%ENVで環境変数を格納する特殊なハッシュを操作することが出来る。

更にパッケージEnvを使うことで、$PATHなど環境変数と同じ名前の変数をその環境変数として使用することが出来るようになる。

 

エラー処理

die():           エラーメッセージを表示してスクリプトを終了する。

$!:              Perlスクリプトがそれをキックしたプロセスに返す値。(例えばシェルスクリプトが呼び出した場合は、シェルスクリプトはその変数を$?で受け取る)

 

./die.pl

        if (<条件式>) {

        $! = 1;

        die(<メッセージ>);

 

引数

@ARGVという特殊なリストに格納される。

引数の値を使うときは、リストコンテキストで使う。

引数の個数を使うときは、スカラーコンテキストで使う。

 

eval()

引数をPerlのコマンドとして解釈し、実行する関数。

> eval(print(1+2));

3

 

バッククォート(`<command>`

UNIXのシェルと同様、バッククォート(`<command>`)で囲まれた部分はそのコマンドの返す情報が代入されて返される。

 

特殊変数:

<STDIN>

標準入力を読み込む

 

$_

いわゆる「山田君、ええとこの間のアレどうなってたっけ?」の「アレ」。

Perl最大の特徴。

省略された変数の内容を保持する。

例)

foreach (@array) {

         print $_;

}

この文は完全に有効である。

本来であれば、foreachの後におかれるべき@arrayの各要素を格納する変数(例えば、$val)が省略されている。

上の文は以下の文とまったく同様の働きをするのである。

foreach $val (@array) {

         print $val;

}

これ以外にも様々な局面でデフォルトで$_が操作される。例えばマッチ演算子などもデフォルトの捜査対象は、$_である。

 

$.

現在の行番号

 

<*>     (グロブ)

グロブと呼ばれる、ディレクトリ内のファイルを返すコマンド

Perl5以降は、glob()でもOK.

 

ファイル入出力:

open(IN, “ファイル名”)           # INは任意のファイルハンドラ。成功すると1(true)を返す。この場合ファイルは入力ファイルとして開かれる。

open(OUT, “>ファイル名”)         # OUTは任意のファイルハンドラ。成功すると1(true)を返す。ファイル名の前の”>”は出力ファイルを新たに作成することを示す。

open(OUT, “>>ファイル名”)        # OUTは任意のファイルハンドラ。成功すると1(true)を返す。ファイル名の前の”>>”は出力を存在するファイルに追加することを示す。

print OUT “文字列               # 何故だか、OUTの後のカンマは不要。あるとコンパイルエラーになる。

 

開いたファイルを扱うには、例えば、

open(IN, "ファイル名");

@files = <IN>;

foreach my $line (@files) {

print ($line);

}

close(IN);

 

コマンド入出力:

open(OUT, “| コマンド”)          # OUTPerl内での仮想ファイルハンドラ。Perlでの実行結果をOUTに格納し、OUTcloseするとコマンド前の”|”により、コマンドにパイプする。

open(IN, “コマンド |”)           # INPerl内での仮想ファイルハンドラ。コマンドの実行結果をINに格納し、以後INをファイルハンドラと同様に扱うことが出来る。

 

 

 

マッチ演算子:

/regexp/                  (マッチのみ)

s/ regexp /target/        (文字列置換)

tr/ regexp /target/       (文字置換)

置換の例)

my $line = "abc_def\n";

print $line;

$line =~ s/_/./g;

print $line;

この場合、出力は、

    abc_def

    abc.def

となる。置換演算子はその対象となる文字列を格納する変数(この場合$line)内の文字列を置換し、その結果をその変数に上書きしていることに注意しよう。

=~の左辺に変数を指定しない場合は、$_特殊変数がその捜査対象となる)

 

演算子=~:

s///tr///$_以外に適用したいときに=~でその左辺の変数が操作できる。

 

マッチに関係する特殊変数:

$`            マッチした部分の前の部分を返す

$&            マッチした部分を返す

$’           マッチした部分の後の部分を返す

$1, $2, ...   マッチ演算子内部にて()でくくられている部分を順番に記憶する

 

Perlで使える正規表現一覧:

文字クラス

[abc]          abcのどれか

[a-z]          aからzのどれか(つまり小文字)

[^abc]         aでもbでもcでもない

\d             数字

\D             数字以外

\w             英数字

\W             英数字以外

\s             空白文字

\S             空白文字以外

\b             単語境界

.              任意の一文字

 

繰り返し(xはある文字)

x*             0回以上の繰り返し

x+             1回以上の繰り返し

x?             0回か1

x{5}           5回繰り返し

x{3,}          3回以上繰り返し

x{3,5}         3回以上、5回以下繰り返し

 

グループと選択

hi(na)+        hina, hinana, hinanana....にマッチ

hina|yui       hinayuiにマッチ

hina(ko|chan)  hinakohinachanにマッチ

hina(ko|chan){2,3}

               hinakoko, hinakokoko, hinakochan,などにマッチ

 

iスイッチ:

マッチ演算子の末尾にiをつけると大文字小文字を無視する。

 

mでの区切り文字の変更:

m#パターン#と書くと、#がマッチ演算子として扱われる。

 

最大マッチと最小マッチ:

Perlは基本的には最大マッチだが、繰り返しの後に?をつけると最小マッチとなる。

 

文字コード:

特定の文字コードを使用するには、

use encoding ‘<文字コード>’

 

ord():  文字をコード値に変換する

chr():  コード値を文字に変換する

 

Windows環境での注意:

Windows環境でマッチ演算子を用いて文字列を抽出する場合に、改行の除去でハマる場合がある。

ハマリ例)

/^U:(.+)$/

この例は、行頭に”U:”がある行の残りの部分文字列を行末までマッチさせたい例だが、この方法によって抽出された文字列の改行はchompでは取り除けない。

この問題を回避するには、例えば以下のようにする。

回避例)

/^U:(.+)\r\n/

こうすれば、Windowsでの改行コードの直前の文字列までにマッチさせることが出来る。

 

注)多分、もう少しよい方法があるのでしょうが、今回はこれで回避しました(200878日)

 

文字列操作関数:

部分文字列 = substr(対象文字列、開始位置、長さ)

文字列長 = length(対象文字列)

 

ソート関数:

リスト = sort(配列)

また、ソート順を以下のソート指定により変更することが出来る。

sort{$a cmp $b}(配列)            #文字列昇順

sort{$b cmp $a}(配列)            #文字列降順

sort{$a <=> $b}(配列)            #数値昇順

sort{$b <=> $a}(配列)            #数値降順

注)$a$bの変数名は取り替えられいが、ローカル変数なので、プログラムの他の部分に影響することはない。

 

 

 

PuTTyとの組み合わせで起こった問題:

1)フルパスの指定でハマる

cygwinでフルパスの指定時に/cygdrive/hなどとすると、pscpなどのコマンドにうまく渡せない。

use Env;を宣言し、$HOME/..(実体はh;\)とするなどしてファイルへの参照を指定するとよい。

2)パスワードの指定

-pw にてパスワードの指定が可能。

 

特集変数$?を用いたすごいコマンド:

system(@cmd);

if ($? == -1) {

    print("failed to execute: $!\n");

} elsif ($? & 127) {

    printf("child died with signal %d, %s coredump.\n", ($?&127), ($?&128)? 'with': 'without');

} elsif ($? != 0) {

    printf("exited with value %d\n", $?>>8);

}

return $?;

 

この一連の処理はいったい何をしているかというと、system(@cmd)によって実行されたコマンド(@cmdには適切なUNIXのコマンドが文字列で入っているとする)の戻り値を解析し、その結果を表示している。これは以下の事実に基づいている。

UNIXのコマンドの終了ステータスは、16ビットの数値で、下位バイトはプロセス終了時に送られたシグナル 番号、上位バイトは終了ステータス(シグナル番号が0の場合のみ)である。下位バイトの 上位ビットは、コアファイルが作成された時にセットされる。」

http://iblinux.rios.co.jp/PyJdoc/lib-j/module-posix.html

 

よって、

-         ($?&127)はこの終了ステータスの下位バイトのみを整数化、すなわちプロセス終了時のシグナル番号

-         ($?&128)下位バイトの上位ビット(右から数えて8桁目)が1(true)か、0(false)か、言い換えればコアファイルが作成されたかどうか

-         ($?>>8)は上位ビットを整数化したもの、すなわち終了ステータス(ただし、シグナル番号が0のときのみ)

となる。(さすが、Anders!