2013年3月19日火曜日

連続する文字に一致させる

AAやBB等、同じ文字が連続する場合に一致させるには、正規表現の後方参照を使います。
後方参照とは、括弧の中にマッチしたテキストを表します。
例えば、\1は最初に一致した括弧の文字を表し、\2は2番めに一致した括弧の文字を表します。


my @strings = (

"すす、好きです",
"あ、愛してる",
"ABBA",
"Change");

foreach my $aStr(@strings) {
if ($aStr=~/(\S)\1/) {
print "$aStr\n";
}
}



上記では、スペース以外の文字を表す\Sを括弧でくくり、後方参照\1で一致した括弧の文字と一致するかをチェックすることで文字の連続をチェックしています。

結果は以下のようになります。

すす、好きです
ABBA



2013年3月18日月曜日

エラー発生時に自動的に死亡するようにする

Perlのバージョン5.10以降からは「use autodie」を付けることでファイルIO等、エラーが発生した時に自動的に死亡するようにすることができるようになりました。

従来


open $IN, "<:utf8", $ARGV[0] or die "Can't open file $!"; # ファイルがオープン出来なければ死亡することを明示


上記ではオープンのたびに正常にオープンできたかチェックし、エラーなら死亡するようにしています。


新しいバージョン


use autodie;
open $IN, "<:utf8", $ARGV[0]; # もうエラーについて書かなくても良い!



当然、死亡理由等、必要な情報を吐き出して死亡してくれます。


出力フォーマットを指定する

Perlで文字列を出力するには、printを使いますが、フォーマットを指定して出力するには、printfを使います。

%dは10進整数を表示し、%sは文字を表示します。


my $num=55.55;
printf "数値:%d 文字:%s\n", $num, $num;



%dは小数以下は切り捨てられます。結果は以下のようになります。


数値:55 文字:55.55





%gは、perlが小数、整数、浮動少数等、状況に応じて適宜判断してくれます。


printf "適宜当てはめた値:%g %g %g\n", 0.5, 0.0000000234567, 10;



結果は以下のようになります。


適宜当てはめた値:0.5 2.34567e-08 10





文字(%s)や整数(%d)等、%とdやs等の間に数字を指定することで桁数を指定できます。


my $num=55.55;
printf "数値:%6d 文字:%10s 適宜当てはめた値:%6g\n", $num, $num, $num;



結果は以下のようになります。


数値:    55 文字:     55.55 適宜当てはめた値: 55.55


上記は桁数を指定したので、黄色い部分にスペースが挿入されています。


更に、空白ではなく0で埋めたり、左寄せしたり、四捨五入もできます。パーセント自体を出力する時は、%%と2個連続させます。



my $num=55.55;
printf "0で埋める:%06d 左寄せ:%-6d 四捨五入または浮動少数:%4.0f %%\n", $num, $num, $num;




結果は以下のようになります。


0で埋める:000055 左寄せ:55     四捨五入または浮動少数:56 %









静的変数

Perlで静的変数(C言語でいうところのstatic変数)を使用するには、stateを使用します。
Perlのバージョン5.10以降の機能なのでuse 5.010を付けることに注意が必要です。
また、バージョン5.14時点ではstateを配列(リスト)や辞書(ハッシュ)につけることはできないようです。



#!/opt/local/bin/perl
use warnings;
use 5.010;

print "号令!\n";
while (my $line = <STDIN>) {
if (!defined($line)) { last; };
&marine;
}

sub marine {
state $sailor_number = 0;
$sailor_number++;
print "I'm sailor $sailor_number!\n";
}



結果は以下のようになります。


号令!

I'm sailor 1!

I'm sailor 2!

I'm sailor 3!

I'm sailor 4!

I'm sailor 5!

I'm sailor 6!

I'm sailor 7!





foreachで使用した変数は元に戻る

Perlでは、foreachループで使用した変数は自動的に元の値に戻ります。

例えば、


@strings = qw(neko inu tori);
$str = "empty";
foreach $str(@strings) {
print "str=$str\n";
}
print "str=$str\n"; # ループ内の変更は保持されない



結果は以下のようになります。


str=neko
str=inu
str=tori
str=empty


$strの値はループ内で変更されますが、ループを抜けると元の値に戻っています。

当たり前ですが、for文ではこのようなことはありません。
念のためfor文のループ処理も書いておきます。


@strings = qw(neko inu tori);

$count = 0;
$str = "empty";
for($count=0 ; $count < scalar(@strings) ; $count++) {
$str = $strings[$count];
print "str=$str\n";
}
print "count=$count\n"; # ループ内の変更が反映される
print "str=$str\n"; # ループ内の変更が反映される




結果は以下のようになります。


str=neko
str=inu
str=tori
count=3
str=tori



for文のループ内で変更された$strと$countの値は、ループを抜けても最後に格納された値が反映されています。(自動的に元には戻りません。)


2013年3月8日金曜日

連想配列からキーと値の組みを取り出す

連想配列(ハッシュ)からキーと値を一度に取り出すには、eachを使います。



%hash = (
'D' => 4,
'E' => 9,
'C' => 1,
'A' => 5,
'B' => 8,
);

while (@key_value = each %hash) { # 辞書からキーと値の組みを取り出す
print "$key_value[0]:$key_value[1]\n";
}



eachでは「キー」と「値」の配列が取得できます。
結果は以下のようになります。


A:5
C:1
D:4
B:8
E:9



2013年3月7日木曜日

連想配列(ハッシュ)をキー順にソート

ハッシュをキー順にソートするには、以下のようにします。


%hash = (
'D' => 4,
'E' => 9,
'C' => 1,
'A' => 5,
'B' => 8,
);


@sorted_key = sort { $a cmp $b } keys %hash; # ハッシュをキーの昇順にソート

foreach $aKey(@sorted_key) {
print "[$aKey]:$hash{$aKey}\n";
}


結果は以下のようになります。


[A]:5
[B]:8
[C]:1
[D]:4
[E]:9



注意が必要なのは、連想配列自体に順序があるわけではないので、連想配列の中身の順序が変わるわけではないということです。
ソートするのはあくまでもキーについてだけです。