ChaichanPapa-World !

燈明日記(2009/07

◆ インデックス

◆ 2009年7月

2009-07-31 雑記(中学バスケット、京北中、梅丘中)

昨日は、久々に23時過ぎまでの残業で、帰ってきたのが今日の0時15分頃になりました。

さすがに、ブログを更新する気力がなく、お風呂に入ってすぐ寝ました。


で、思ったのですが本当に忙しい人は、ブログなど書く時間がないんだなって・・・。

毎日更新している人って、よほどの暇人かアフィリエイトな人ですかね(^^;


実は、今日も忙しかったです。昨日と今日で一週間分の仕事をした感じです。

そうそう、中学バスケットの夏季都大会は、京北中が優勝しましたね。


京北中は、高校バスケットの都大会でも優勝できるじゃないかなって思います。

スタメンの身長が175〜190ですよ! 高校生より大きいじゃん。


しかし、準優勝の梅丘中は、新人戦・春季都大会・夏季都大会と3回も京北中に敗れてますね。

いつも、2回〜準決勝で敗れていたので、今回は、どっちが強いんだと思っていた足立九中にも勝って、事実上のナンバー2になりました。


暑い中、これから全国大会や関東大会・・・、関係者の皆さま本当にご苦労様です!

2009-07-29 ZIPファイルの中身を見るには

ZIPファイルを解凍でなく中身だけを見たい場合がありますね。

Windowsでは、ZIPファイルは単にダブルクリックするだけで見れます。

しかし、Linuxではどうするのでしょうか・・・。

tar.gzならtarコマンドのtvzfオプションで見れますが・・・。


◆ 答え:

unzipコマンドのZオプションを使います。


・サンプル表示
$ unzip -Z file.zip
Archive:  file.zip   242 bytes   2 files
-rw-rw-rw-  2.0 unx       66 t- defN 16-Jan-09 19:40 file.txt
-rw-rw-rw-  2.0 unx       66 t- defN 16-Jan-09 19:41 file2.txt
2 files, 132 bytes uncompressed, 34 bytes compressed:  74.2%

もちろん、解凍は、オプションなしに『unzip file.zip』です。

2009-07-28 三鷹七中バスケット部完全燃焼!!

今日、府中六中の体育館で夏季都大会の第三戦がありました。

三鷹七中の対戦相手は、文京区の常勝京北中(新人戦優勝・春季大会優勝・全国2位)でした。


京北のスタメンの身体能力は、中学生はもちろん高校クラスでもトップレベルですね!!

スタメンが出ていた前半は、大人と子供の試合で、スタメンが引っ込んだ後半が、互角の勝負で面白かったです。


結局、126対69の大差で負けてしまいました。

しかし、あの京北から約70点ももぎ取ったのは、最後の最後に良い経験が出来たのだと思いました。


これで、三鷹七中バスケット部3年生の最後の公式戦が終わり、あとは、高校受験勉強が残りました(^o^;

いやー、最後の最後に京北戦とは、完全燃焼ができましたね。たぶん、負けても悔いはないと思います。


実は、私は午後、会社を早退して、府中六中の体育館へ駆けつけたのでした。

後半で結構活躍できた三男も悔いはないでしょう。


最後に、三鷹七中バスケット部の関係者のみなさん(特に3年生のお母さん)、お疲れ様でした!

小学校時代のミニバス(ファルコン)から6〜8年間、本当にお疲れ様でした!


追記(2009/07/29)

バスケ少年が、万が一このブログを読んでいたらを想定して、京北中の2つのテクニックをメモしときます。

  1. ドリブルでの相手ボールは奪えないものだと思っていませんか・・・京北の選手はいとも簡単に奪えるのです。相手に物凄いプレッシャーかけ奪い取るのです。(これが全国レベルなのか・・・と感じさせられた)
  2. パスは受け取った瞬間にパスする。つまり、未来の状況をつねに意識できている(あっという間に反対ゴールから自ゴール下にボールをパスで運ぶ)

バスケットを通しての成長した子達へ

君達が頑張れたのは、自分ひとりの力ではなく、周りのお母さんやお父さんをはじめ、諸先生方、先輩後輩がいたからこそ頑張れたのです。まずは周りのすべての人に感謝して、高校受験勉強を頑張ってください!


特にお母さん方、早起きでのお弁当作り、本当にご苦労さまでした!

2009-07-26 三鷹七中バスケット部、夏の都大会、第一回戦突破!!

今日、府中一中の体育館で都大会の第一回戦がありました。

三鷹七中の対戦相手は、葛飾区の青葉中でした。


三鷹七中は激しい練習の末、レギュラー5人中4人が捻挫の治療中で、満身創痍の中の試合でした。

試合は、終わり20秒前75対74で一点差まで追い上げられ、こちがら反則をとられ、フリースロー2本・・・。

1本で同点、2本で逆転される場面になりました。


あと20秒を切っているし、万事休すと思いましたが、この場面でさすがに緊張したのか、2本とも入らず!!

そのあと、こちらが1点決めて、76対74で辛うじて勝ちました。


実は、最後の相手のフリースローのとき、両手両腕に痺れが来たのです。

自分でも驚きました。試合が終わった時は、自然と涙が溢れ出てきました。

こちらは、歓喜の渦でしたが、相手チームの選手は泣いていましたね。両方のチーム、本当に頑張りました。


長男、次男、三男とバスケの試合を小学校の時から見てきましたが、痺れがくるほどの試合は初めてでした。

本当に凄い試合、ありがとう!!

2009-07-26 WIN系でフォルダをコピーするには

Perlでは、system関数やバッククォートで外部コマンドが実行できます。


linux系ではcpコマンドの-rオプションで、インタラクティブなしにディレクトリ(フォルダ)のコピーができます。

しかし、WIN系では、copyコマンドはファイルのコピーで、xcopyコマンドではインタラクティブなフォルダコピーです。


なので、Perlで、WIN系で、インタラクティブなしで、フォルダのコピーをするには、外部コマンドでは、難しいわけです。

そんなときは、File::Copy::Recursiveモジュールのdircopyが使えます。

ただ、標準モジュールでないので、CPANからインストールが必要です。


◆サンプルソース
use strict;
use warnings;
use File::Copy::Recursive qw(dircopy);

dircopy 'back' , 'back2' or die $!;

◆モジュールインストール
C:\> ppm install File::Copy::Recursive

◆参考リンク

http://perldoc.jp/docs/modules/File-Copy-Recursive-0.06/Recursive.pod

2009-07-25 ずーっと使ってた物が次々壊れた!

形あるのもは壊れるというけれど、長年使っていた『洗濯機』と『ドライヤー』と『蛍光燈』がほぼ同時に壊れた!


蛍光燈はグローランプかと思ったらグローランプが付いていないタイプのやつで、こんなのあったんだって感じ(常識が覆った)。ドライヤーは、即日買ってきて事なきに・・・。


問題は、洗濯機、これ今日の朝に壊れた。洗濯途中で止まったので、とりあえず脱水だけはと思って、自転車で近所のコインランドリーにいったら、店が潰れてた・・・。しょうがないので、その足で義妹の家にいったら、留守だった・・・。ついていないときは、重なるもんですねorz


で、手で絞りながら2階のベランダで干していると、次男が手伝ってくれてた。大き目の洗濯物は2人掛かりで絞ったよ。親子でいい感じだった。次男のやさしさだけが救いだった。来週の月曜にシャープの修理屋さんが来てくれることになった。


普段、あたりまえのように存在して生活に溶け込んでいるものが、突然壊れると、あたりまえって、実は大変なことなんだなぁ・・・ってつくづく思う。もっと、『あたりまえ』に感謝しないとね!


しかし、万が一、洗濯機を買い換えるはめになったら、今回の寸志のボーナスがふっとぶな、そうなったら後の望みは、サマージャンボだけだぁ・・・。

2009-07-24 雑記(小飼弾・正規表現・アスペルガー症候群)

昨日は、月に一度の宿直(某教会)で、日記が一日空いてしまいました。


先日のブログの記事が、小飼弾氏のブログに取り上げられ、その日は500近くアクセス数が増えました。

その影響で、念願のブログスカウターが初の1500を突破しました(パチパチ)。

弾さん、ありがとうございました!


今日は、正規表現の威力を実感させらた日でした。やはりテキスト加工処理は正規表現ですね。

そうそう、以下の正規表現の記事、自分ながらよくまとめられたよ! もしよかったら、チェックしてみて下さい!


先日、テレビを見ていてたら、空気読めない病(アスペルガー症候群)のドキュメントをやっていた。

見ていると、次から次へと症状が自分と重なる!

もしかしたら、自分もアスペルガー症候群か?

病気だったんだ・・・と思うとなぜか安心感が湧いてきた・・・、オイ!本当にアスペルガー症か・・・。

2009-07-22 雑記(ExcelVBAとPerlCGI・選挙・皆既日食・中学校バスケット都大会)

いろいろ書きたいことはあるのですが、練りきれず、とりあえず、ネタ切れです。

仕事は、ExcelVBAとPerlCGIを交互にコーディングしています。

はじめのうちは、微妙な違いにへきえきしていましたが、今は両方とも手足のごとく書けますね(オイ自慢かよ)。


選挙は、民主が有利との予想ですが、蓋を開けてみたらどうでるか・・・資本主義の大元が崩壊した今、共産と社民が伸びそうですね。

とにかく、アメリカに抵抗できる党が伸びて欲しい。


皆既日食は、そんなに感動的なことなのですかね。悪石島に行った人お疲れ様でした。残念でしたね。


今度の日曜日から、中学校バスケット都大会『夏の大会』です。

三男は中学3年で、最後の大会になります。ガンバレ!!三鷹七中

2009-07-21 雑記(頑張りすぎと限界の境目が難しい・・・)

真夏の暑い時に、朝から夜まで激しい練習をして怪我人が続出し、他の子達も疲労困憊・・・。

しかし、この状態を乗り越えて、勝ち続けたチームが栄光をつかむことができるのかも。

命を削って限界まで、頑張ることには、確かに意味があることだと思し、その中に学びもあるのだろう。

しかし、万が一、途中で命を落としたら、もともこもなるなるし・・・。

どこまでが限界なのか難しい。

親の言うことは聞かないし、後は無事を祈ることしかできない。


あっそうそう、先日の『配列とハッシュの要素数の求め方』で『配列のハッシュのハッシュ』が抜けていたので追加しました。

2009-07-20 Perlの謎(その10)サブルーチンの呼び出し方

予告したサブルーチンの呼び出し方の謎です。

しかし、予告した割りには、上手くまとまらなかったのですが・・・以下のようになりました。


◆ イントロ

まず、Perlでのサブルーチンは関数と等価です。

そして、関数の呼び出し方には、『&』のファニー文字を付けたり、付けなかったり・・・。

また、関数名の後に『()』小カッコを付けたり、付けなかったり・・・。

またまた、『&』も『()』も付けなく、ベアワードになったりと・・・。


これらは、『組み込み関数やインポートしたモジュール関数』と『ユーザ定義関数』で意味が違ってきます。

なので、各々について対比して解説をしてみました。


尚、以下は、あくまでも私のコーディング方針で、強制的なものではありません。


◆ 『&』ファニー文字について

組み込み関数やインポートしたモジュール関数は、『&』ファニー文字は付けない。

組み込み関数等に『&』を付けるとエラーになる。(ユーザ定義関数を探しに行ってエラーとなる)


ユーザが定義できる関数(サブルーチン)は、『&』を付ける方がよい

これは、ユーザ定義関数でも『&』を付けないで呼び出せますが、同名の組み込み関数等がある場合、組み込み関数が優先され、ユーザ定義関数は無視されます。なのでユーザ定義関数は『&』を付ける方がよい

いろいろな理由で『&』を付けず、ユーザ定義関数は関数名の後に『()』小カッコを付ける方がよい。


しかし、万が一、組み込み関数とユーザ定義関数が同名になった時は、『&』でユーザ定義関数を呼び出すことができる。

use strict;
use warnings;

my $hoge1 = time;   # 組み込み関数
my $hoge2 = &time;  # ユーザ定義関数

print $hoge1 , "\n";
print $hoge2 , "\n";

sub time {
    return 'hoge';
}

◆ 関数名の後の『()』小カッコについて

組み込み関数やインポートしたモジュール関数は、『()』小カッコを付けない方がよい。

カッコを付けてもOKですが、ユーザ定義関数以外であることを明示するために『()』を付けない方がよい。


ユーザが定義できる関数(サブルーチン)は、『()』小カッコを付ける。

関数をロジックの前置きに定義すると、カッコなしでもOKですが、そうしない。『()』小カッコを付けてユーザ定義関数を明示する。

use strict;
use warnings;

my $hoge1 = localtime time;    # 組み込み関数
my $hoge2 = &localtime(time);  # ユーザ定義関数

print $hoge1 , "\n";
print $hoge2 , "\n";

sub localtime {
    return $_[0];
}

◆ 引数のない関数について

引数のない場合の組み込み関数やインポートしたモジュール関数は、ベアワードにする。

引数のない場合のユーザが定義できる関数(サブルーチン)は、『&』『()』を付ける方がよい。


◆ ユーザ定義関数は、『&』をつけない?

前に、bingo_nakanishさんに『サブルーチンの頭に&は普通つけない』と教えて頂いたのですが・・・。

組み込み関数と同名のユーザ定義関数を定義したときは、どうしても『&』付きでないと呼び出せないのです。

また、現在、組み込み関数と同名がないユーザ定義関数を作って『&』無しで呼んで上手くいっていても、将来、同名の組み込み関数が出来る可能性もあるわけです。

すると、ユーザ定義関数でなく、組み込み関数が呼ばれるようになり、上位互換性がなくなり・・・。

なのでユーザ定義関数は、『&』をつけたほうがよいと思うのです。どうでしょうか?


『&』は、基本的につけません。これに関しては以下のリンク先を参照願います。

また、id:miyagawa氏から、以下のようなコメントも頂きました。

将来組み込み関数が増えた場合でも、それらの関数は use feature しないと有効にならない仕組みになっている(5.10のsay や givenなど) ので、何もなしに動かなくなる、ということはないはず。


◆ 結論

結局、前にbingo_nakanishさんに教えて頂いた通りでした(^o^)

2009-07-19 ベランダから撮った『虹』

家の二階のベランダから次男が携帯で撮影した『虹』です。

珍しいので、アップしてみました。

20090719183800


そう言えば、昨日は、調布の多摩川の花火大会で、打ち上げ花火もよく見えました!

今年は、いつもより、打ち上げ距離が高かったようですね。

2009-07-19 配列とハッシュの要素数の求め方

Perlの場合、複雑なデータ構造は、配列とハッシュの組み合わせです。

通常、配列やハッシュを処理する時は、ループになりますね。

その時に、ループの最大値を指定しないとなりません。

ループの最大値は、普通、配列やハッシュの要素数-1になります。


実は、複雑なデータ構造の時、ループの最大値を求めるのに悩む時があるのです。

そこで、以下にアンチョコを用意してみました。

参考になれば、幸いです。


◆ 基本的な配列とハッシュの要素数の求め方(最大インデックスもあり)

◆ アンチョコ
use strict;
use warnings;

print "◆ 配列 -----------------------------------------\n";
my @aa = (1, 2, 3);
print $#aa, "\n";                     # 配列最大インデックス
print scalar(@aa), "\n";              # 配列要素数
print $aa[0], "\n";                   # 要素アクセス例


print "◆ ハッシュ -------------------------------------\n";
my %hh = (a => 1, b => 2, c => 3);
print scalar(keys(%hh)), "\n";        # ハッシュ要素数
print scalar(values(%hh)), "\n";      # ハッシュ要素数
print $hh{a}, "\n";                   # 要素アクセス例


print "◆ 配列の配列 -----------------------------------\n";
my @aa_aa = ([1, 2, 3, 4], 
             [5, 6, 7, 8], 
             [9, 10, 11, 12]);
print $#aa_aa, "\n";                  # 1次元配列最大インデックス
print scalar(@aa_aa), "\n";           # 1次元配列要素数
print $#{$aa_aa[0]}, "\n";            # 2次元配列最大インデックス
print scalar(@{$aa_aa[0]}), "\n";     # 2次元配列要素数
print $aa_aa[0][0], "\n";             # 要素アクセス例


print "◆ 配列のハッシュ -------------------------------\n";
my %hh_aa = (a => [1, 2, 3], 
             b => [4, 5, 6], 
             c => [7, 8, 9]);
print scalar(keys(%hh_aa)), "\n";     # 1次元ハッシュの要素数
print scalar(values(%hh_aa)), "\n";   # 1次元ハッシュの要素数
print $#{$hh_aa{a}}, "\n";            # 2次元配列最大インデックス
print scalar(@{$hh_aa{a}}), "\n";     # 2次元配列要素数
print $hh_aa{a}[0], "\n";             # 要素アクセス例


print "◆ ハッシュの配列 -------------------------------\n";
my @aa_hh = ({a => 1, b => 2}, 
             {c => 3, d => 4});
print $#aa_hh, "\n";                     # 1次元配列最大インデックス
print scalar(@aa_hh), "\n";              # 1次元配列要素数
print scalar(keys(%{$aa_hh[0]})), "\n";  # 2次元ハッシュの要素数
print scalar(values(%{$aa_hh[0]})), "\n";# 2次元ハッシュの要素数
print $aa_hh[0]{a}, "\n";                # 要素アクセス例


print "◆ ハッシュのハッシュ ----------------------------\n";
my %hh_hh = (x => {a => 1, b => 2}, 
             y => {c => 3, d => 4});
print scalar(keys(%hh_hh)), "\n";        # 1次元ハッシュの要素数
print scalar(values(%hh_hh)), "\n";      # 1次元ハッシュの要素数
print scalar(keys(%{$hh_hh{x}})), "\n";  # 2次元ハッシュの要素数
print scalar(values(%{$hh_hh{x}})), "\n";# 2次元ハッシュの要素数
print $hh_hh{x}{a}, "\n";                # 要素アクセス例


print "◆ 配列の配列の配列--------------------------------\n";
my @aa_aa_aa = ([[1, 1], [2, 2]], 
                [[3, 3], [4, 4]], 
                [[5, 5], [6, 6]]);
print $#aa_aa_aa, "\n";                  # 1次元配列最大インデックス
print scalar(@aa_aa_aa), "\n";           # 1次元配列要素数
print $#{$aa_aa_aa[0]}, "\n";            # 2次元配列最大インデックス
print scalar(@{$aa_aa_aa[0]}), "\n";     # 2次元配列要素数
print $#{$aa_aa_aa[0][0]}, "\n";         # 3次元配列最大インデックス
print scalar(@{$aa_aa_aa[0][0]}), "\n";  # 3次元配列要素数
print $aa_aa_aa[0][0][0], "\n";          # 要素アクセス例


print "◆ 配列の配列のハッシュ----------------------------\n";
my %hh_aa_aa = (a => [[1, 2], [3, 4]], 
                b => [[5, 6], [7, 8]]);
print scalar(keys(%hh_aa_aa)), "\n";            # 1次元ハッシュの要素数
print scalar(values(%hh_aa_aa)), "\n";          # 1次元ハッシュの要素数
print $#{$hh_aa_aa{a}}, "\n";                   # 2次元配列最大インデックス
print scalar(@{$hh_aa_aa{a}}), "\n";            # 2次元配列要素数
print $#{$hh_aa_aa{a}[0]}, "\n";                # 3次元配列最大インデックス
print scalar(@{$hh_aa_aa{a}[0]}), "\n";         # 3次元配列要素数
print $hh_aa_aa{a}[0][0], "\n";                 # 要素アクセス例


print "◆ 配列のハッシュの配列--------------------------\n";
my @aa_hh_aa = ({a => [1, 1], b => [2, 2]}, 
                {c => [3, 3], d => [4, 4]});
print $#aa_hh_aa, "\n";                         # 1次元配列最大インデックス
print scalar(@aa_hh_aa), "\n";                  # 1次元配列要素数
print scalar(keys(%{$aa_hh_aa[0]})), "\n";      # 2次元ハッシュの要素数
print scalar(values(%{$aa_hh_aa[0]})), "\n";    # 2次元ハッシュの要素数
print $#{$aa_hh_aa[0]{a}}, "\n";                # 3次元配列最大インデックス
print scalar(@{$aa_hh_aa[0]{a}}), "\n";         # 3次元配列要素数
print $aa_hh_aa[0]{a}[0], "\n";                 # 要素アクセス例


print "◆ 配列のハッシュのハッシュ--------------------------\n";
my %hh_hh_aa = (x => {a => [1, 1], b => [2, 2]}, 
                y => {c => [3, 3], d => [4, 4]});
print scalar(keys(%hh_hh_aa)), "\n";            # 1次元ハッシュの要素数
print scalar(values(%hh_hh_aa)), "\n";          # 1次元ハッシュの要素数
print scalar(keys(%{$hh_hh_aa{x}})), "\n";      # 2次元ハッシュの要素数
print scalar(values(%{$hh_hh_aa{x}})), "\n";    # 2次元ハッシュの要素数
print $#{$hh_hh_aa{x}{a}}, "\n";                # 3次元配列最大インデックス
print scalar(@{$hh_hh_aa{x}{a}}), "\n";         # 3次元配列要素数
print $hh_hh_aa{x}{a}[0], "\n";                 # 要素アクセス例


print "◆ ハッシュの配列の配列--------------------------\n";
my @aa_aa_hh = ([{a => 1, b => 2}, {c => 3, d => 4}], 
                [{e => 1, f => 2}, {g => 3, h => 4}]);
print $#aa_aa_hh, "\n";                         # 1次元配列最大インデックス
print scalar(@aa_aa_hh), "\n";                  # 1次元配列要素数
print $#{$aa_aa_hh[0]}, "\n";                   # 2次元配列最大インデックス
print scalar(@{$aa_aa_hh[0]}), "\n";            # 2次元配列要素数
print scalar(keys(%{$aa_aa_hh[0][0]})), "\n";   # 3次元ハッシュの要素数
print scalar(values(%{$aa_aa_hh[0][0]})), "\n"; # 3次元ハッシュの要素数
print $aa_aa_hh[0][0]{a}, "\n";                 # 要素アクセス例


print "◆ ハッシュのハッシュの配列--------------------------\n";
my @aa_hh_hh = ({x => {a => 1, b => 2}, y => {c => 3, d => 4}}, 
                {z => {e => 1, f => 2}});
print $#aa_hh_hh, "\n";                           # 1次元配列最大インデックス
print scalar(@aa_hh_hh), "\n";                    # 1次元配列要素数
print scalar(keys(%{$aa_hh_hh[0]})), "\n";        # 2次元ハッシュの要素数
print scalar(values(%{$aa_hh_hh[0]})), "\n";      # 2次元ハッシュの要素数
print scalar(keys(%{$aa_hh_hh[0]{x}})), "\n";     # 3次元ハッシュの要素数
print scalar(values(%{$aa_hh_hh[0]{x}})), "\n";   # 3次元ハッシュの要素数
print $aa_hh_hh[0]{x}{a}, "\n";                   # 要素アクセス例


print "◆ ハッシュの配列のハッシュ--------------------------\n";
my %hh_aa_hh = (z1 => [{a1 => 1, b1 => 2}, {x1 => 1, y1 => 2}], 
                z2 => [{a2 => 1, b2 => 2}, {x2 => 1, y2 => 2}]);
print scalar(keys(%hh_aa_hh)), "\n";              # 1次元ハッシュの要素数
print scalar(values(%hh_aa_hh)), "\n";            # 1次元ハッシュの要素数
print $#{$hh_aa_hh{z1}}, "\n";                    # 2次元配列最大インデックス
print scalar(@{$hh_aa_hh{z1}}), "\n";             # 2次元配列要素数
print scalar(keys(%{$hh_aa_hh{z1}[0]})), "\n";    # 3次元ハッシュの要素数
print scalar(values(%{$hh_aa_hh{z1}[0]})), "\n";  # 3次元ハッシュの要素数
print $hh_aa_hh{z1}[0]{a1}, "\n";                 # 要素アクセス例


print "◆ ハッシュのハッシュのハッシュ----------------------\n";
my %hh_hh_hh = (z1 => {x1 => {a1 => 1, b1 => 2}, y1 => {c1 => 3, d1 => 4}}, 
                z2 => {x2 => {a2 => 1, b2 => 2}, y2 => {c2 => 3, d2 => 4}});
print scalar(keys(%hh_hh_hh)), "\n";              # 1次元ハッシュの要素数
print scalar(values(%hh_hh_hh)), "\n";            # 1次元ハッシュの要素数
print scalar(keys(%{$hh_hh_hh{z1}})), "\n";       # 2次元ハッシュの要素数
print scalar(values(%{$hh_hh_hh{z1}})), "\n";     # 2次元ハッシュの要素数
print scalar(keys(%{$hh_hh_hh{z1}{x1}})), "\n";   # 3次元ハッシュの要素数
print scalar(values(%{$hh_hh_hh{z1}{x1}})), "\n"; # 3次元ハッシュの要素数
print $hh_hh_hh{z1}{x1}{a1}, "\n";                # 要素アクセス例

2009-07-18 配列のインデックスでなく、インデックスの配列?

以下は、弾さんのブログで、たまたま見つけました。

なんか、配列をインデックスに使用していますね。

普通は、配列に対してインデックスがあるのに、以下は配列がインデックスになっています。

つまり、配列のインデックスでなく、インデックスの配列?


◆ 引用(サンプル)
sub make_akhash {
    return sub : lvalue {
        $val{join($;,@_)}
    }
}

my @array  = qw/1 2 3/;
my @array2 = qw/1 2 3/;

my $h = make_akhash();
$h->(@array) = 'foo';
print $h->(@array2);
http://blog.livedoor.jp/dankogai/archives/50936712.html

たったこれだけのロジックだけど、理解するのに3つのハードルがありますね。

◆ クロージャ

関数のリターン値に関数リファレンスを指定して、関数リファレンスが関数の内部変数を使用すると、その変数はスコープを抜けても生きつづけ、カウントアップ等が可能になることかな・・・。

あと、引用のソースには、%valの宣言がありませんね、実際は、以下の感じですかね。

sub make_akhash {
    my %val;
    return sub : lvalue {
        $val{join($;,@_)}
    }
}

◆『$;』多次元配列のエミュレートのための添え字

『$;』はセミーセミコロンといわれ?、ハッシュキーでの見た目はセミコロンだけど、実際のデフォルト値は『\034』とのことです。

つまり、ハッシュのキーにバイナリ値を使う場合は、エミュレートできないということです。

なぜなら、バイナリ値はすべてのコードが対象で、当然『\034』が含まれるからです。


◆『: lvalue』左辺値サブルーチン

普通は変数へ代入しますが、これ、サブルーチンへ代入ができるのです。

それには、sub文のサブルーチン名の後ろに「: lvalue」を追加します。(引用サンプルでは無名サブルーチンなのでsub文の後ろに追加)

そして、代入値は、サブルーチンで一番最後に評価する変数に代入されるみたいです。

詳しくは以下を参照してください。

2009-07-17 グーグルの非常識なデータセンター

前に読んだ本に、グーグルのサーバーは数十万台のクラスタになっているとか、いないとか、とにかく、すごい数のサーバーが稼動しているので、排熱がすごいと思うのだけれど、『データセンターはエアコンを使わないのが常識』とのことです。

とにかく、『温度が上がってきたらデータセンターごと切り替える』とか、『グーグルのデータセンターは月を追いかける』とか、まさに非常識な進化をしているみたいですね・・・。

2009-07-17 ハッシュの要素数を求めるには?

配列の要素数は、配列変数をスカラーコンテキストで評価すると求められます。

では、ハッシュの要素数は、どのように求めればよいでしょうか・・・。

こたえ、keys関数(または、values関数)のリターン値をスカラーコンテキストで評価して求めます。


◆サンプル
use strict;
use warnings;

my %hash = (aaa => 111, bbb => 222, ccc => 333);
print scalar(keys(%hash)), "\n";

◆補足

ちなみに、printで、scalar関数を使わないとリストコンテキストになり、ハッシュのキー値が表示されます。

なので、要素数を表示するときは、scalar関数で強制的にスカラーコンテキストにします。

2009-07-16 ハッシュが空かどうかを調べたい

ハッシュが空かどうかを調べたいときは、以下のサンプルを参考にしてください。

決して、defined()の否定を使わないように、defined()は、スカラーで未定義の判定に使います。


◆サンプル
%hash =();
#%hash = (aaa => 111, bbb => 222, ccc => 333);
if (!%hash) {
    print '空です!', "\n";
}
else{
    print '空でない!', "\n";
}

◆引用

defined(%hash) is deprecated

(D deprecated) defined() は未定義の スカラ 値を調べるので、ハッシュに使っても普通は無意味です。ハッシュが空かどうかを調べたい場合は、例えば単に if (%hash) { # not empty } としてください。

http://perldoc.jp/docs/perl/5.6.1/perldiag.pod

◆リンクメモ

2009-07-15 雑記(『Perl謎(その10)サブルーチン』予告)

今日は、歓送迎会があり、今ちょっと前に帰って来ました。

歓送迎会は盛り上がっていましたが、私はメガネを多分飲み屋さんのどこかに無くしてしまってブルーでした。

結局、見つからない・・・。


仕事の方も今日はブルーでした。

ある条件のときは、ハッシュ変数に代入しないので、if (!defined(%hash)) で引っ掛かるはずなのに引っ掛からない・・・。

今、家で同じようなテストプロを作ってテストしたら、間違いなく引っ掛かる。なにが原因なんだろ・・・。


あと、Perlの次の謎は、『サブルーチン』に決定しました。

この間だ、ビンゴさんに教えていたサブルーチンの呼び方は、組み込み関数は小カッコなしで、ユーザ定義関数は『&』無しの小カッコありと教わりました。

しかし、組み込み関数と同名のユーザ定義関数を定義したときは、どうしても『&』付きでないと呼び出せないのです。


これ、わざわざ、組み込み関数と同名のユーザ定義関数をつくるな・・・って言われそうですが・・・。

そうではなく、現在、組み込み関数と同名でないユーザ定義関数を作って『&』無しで呼んでいるとします。

しかし、将来、同名の組み込み関数が出来る可能性もあるわけです。

すると、上位互換性がなくなります。


なので、ユーザ定義関数は『&』付きで呼び出しましょう・・・という結論になりました。

ユーザ定義関数をリファレンスする時は、必ず『&』が必要ですし・・・

したがって、ユーザ定義関数の呼び出しは、必ず『&』付きでということで・・・どうでしょうか?


この辺を含めて、Perlの謎(その10)サブルーチンを練っています。

期待しないでお待ちください!

2009-07-14 『小池啓仁ワンマンライブ!! on August 30』

f:id:chaichanPaPa:20090625010800j:image:right

えーと、料金(入場料)、書くのを忘れていました。

CHARGE \2000+DRINK \500

です。よろしくお願いいたします。


来る8月30日(18:00)に新宿ミュージックインで『小池啓仁ワンマンライブ』があります!!


今回は、いつもの1人の弾き語りでなく、バックミュージシャンにも参加して頂いて、集客200人を目標に頑張っていますよ!!

もしよろしかったら、お友達もお誘いして、是非、彼の歌を聴いてやってください!!

地元の人は、地元からツアーバスが出る予定です。なので以下のメールアドに連絡ください。


◆メルアド

koikehirohitoアットマークyahoo.co.jp

(メールを出す時は、アットマークは @ に置換してください)


◆『つながり』 By 小池啓仁

Download


◆『扉』 By 小池啓仁

Download


◆『For Me』By 小池啓仁

2009-07-14 最近、気になった記事2つ

不特定多数のPCにウィルスを感染させて、そのすべてのPCから特定のサイトを攻撃する。

掲示板にリンクを張っただけで逮捕される・・・、そろそろ放置掲示板『WEB相談室』も閉鎖しようかな・・・。

2009-07-14 正規表現ブログ完成

ここのところ、ちょこちょこ直していた正規表現ブログが完成しました。

正規表現初心者の人にも分かりやすく解説したつもりです。


あと、昨日の『Perlの謎(その9):Perlでの文字列』は、あまりにもアレだったので、加筆修正しました。

2009-07-13 Perlの謎(その9):Perlでの文字列

VB系とかDOSコマンド系での文字列はダブルクォーテーションです。

また、SQL系での文字列は、シングルクォーテーションです。


Perlでの文字列は、上記両方です。

違いは、ダブルクォーテーションでは変数が展開され、シングルクォーテーションでは展開されません。

また、qクォート演算子とqqクォート演算子も同じ関係で文字列を表します。

my $strdata1 = '文字列1';
my $strdata2 = "文字列2 $strdata1";
my $strdata3 = q{文字列3};
my $strdata4 = qq{文字列4 $strdata3};
print $strdata1, "\n";  # 文字列1
print $strdata2, "\n";  # 文字列2 文字列1
print $strdata3, "\n";  # 文字列3
print $strdata4, "\n";  # 文字列4 文字列3

あと、qwクォート演算子を使うと文字列のリストの入力が楽になりますね。

my @strlist2 = qw{文字列1 文字列2 文字列3};         # 上と等価(ただし、スペースが文字列中にあるときはNG)
print "@strlist1", "\n"; # 文字列1 文字列2 文字列3 
print "@strlist2", "\n"; # 文字列1 文字列2 文字列3

◆補足1:ダブルクォート文字列での特殊文字のエスケープ

たとえば、ダブルクォート文字列にダブルクォートを記述する場合は、その前に \ を置いてエスケープします。

尚、シングルクォート文字列の中でのシングルクォート( ' )のエスケープは( \' )とします。


◆補足2:ダブルクォート文字列で展開される \ による文字エスケープ

以下は、ダブルクォート文字列の中で各々の意味(制御コード)に展開されます。

2009-07-12 民主圧勝

夕方7時過ぎにママと一緒に都議選の投票に行ってきました。

現在22:30頃、民主の圧勝ですね。


自民の菅(すが)氏が都議選寸前まで民主の鳩山さんをイジメていたのが裏目にでましたね。

菅氏、小沢氏もイジメていたので、民主が天下をとったら、オモシロイことになりますね。


最低の大統領ブッシュに擦り寄って貧富の差を広げた小泉氏や政権を投げ出した福田氏や安部氏よりは、ましな麻生さんだけど・・・一国の器ではないみたいですね。普通のおじさんですね。


すみません。低レベルなことを書いてしまいました。

2009-07-12 ExcelVBAでWorksheet_Changeサブルーチンの作成留意点

VBAのWorksheet_Changeサブルーチンは、セルが書き換えられた時に起動されます。

その時に、システムから書き換えられたRangeオブジェクトが渡されます。


このRangeオブジェクトは、実は、一つのセルだけでなく、複数のセルの場合もあるのです。

また、空の場合もあるのです。


要は、複数セルをDelキーで削除したり、単一セルをDelキーで削除したり・・・。

すると、Rangeオブジェクトは一つのセルデータでなく、配列だったり、空だったりするのです。


その場合、処理をしないようにするには、以下のようにします。

複数セルをDelキーで削除した場合は、配列で、IsArray関数を使います。

単一セルをDelキーで削除した場合は、空で、IsEmpty関数を使います。


サンプル
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Sheet2 As Worksheet
Dim Sheet_Save As Worksheet

    '配列だったら Exit Sub
    If IsArray(Target.Cells.Value) Then Exit Sub
    '空だったら Exit Sub
    If IsEmpty(Target.Cells.Value) Then Exit Sub

    Set Sheet_Save = ActiveSheet
    Set Sheet2 = Worksheets("Sheet2")
    Sheet2.Activate
    
    '任意シート(例ではSheet2)の任意の処理を記述する。
    MsgBox "Sheet2"
    
    Sheet_Save.Activate
    Set Sheet_Save = Nothing
    Set Sheet2 = Nothing
End Sub

まぁ、もちろん、複数のセルや空のセルに対する処理が必要な場合は、Exit Subしないでその処理を記述します。

2009-07-12 盂蘭盆会2009

えーと今日は、毎年恒例のお盆の式典が某教会でありました。

毎年恒例だと、本当に一年があっという間に過ぎてしまうというように感じる歳になりました。

とりあえず以下は、過去に書いた盂蘭盆会のブログです。

今回は、教育評論家の川越淑江さんのご講演がありました。

期待しないで聞いていた割りには、結構良い話が聞けました。


子供の躾で、『人さまや世間の迷惑になるとはしてはいけない』と言うより、『人さまや世間のためになる人になりなさい』と言う方がかなり良いとのことでした。

言われると、あーそうか! って感じですが、つい『人さまや世間の迷惑になるとはしてはいけない』と躾てしまう・・・。


また、子育てには、オアシスが必要とのことでした。

このように躾ると家庭がオアシスなる・・・なるほど上手いこと言う。


あと、呼ばれたら『ハイ』と返事するように躾ますが、この『ハイ』は、実は人を拝む『拝』とのことでした。

呼ばれたら『ハイ』と返事をいうことは、呼んだ人を拝むことだったのですね。

2009-07-11 『小池啓仁ワンマンライブ!! on August 30』

f:id:chaichanPaPa:20090625010800j:image:right

来る8月30日(18:00)に新宿ミュージックインで『小池啓仁ワンマンライブ』があります!!


今回は、いつもの1人の弾き語りでなく、バックミュージシャンにも参加して頂いて、集客200人を目標に頑張っていますよ!!

もしよろしかったら、お友達もお誘いして、是非、彼の歌を聴いてやってください!!

地元の人は、地元からツアーバスが出る予定です。なので以下のメールアドに連絡ください。


◆メルアド

koikehirohitoアットマークyahoo.co.jp

(メールを出す時は、アットマークは @ に置換してください)


◆『つながり』 By 小池啓仁

Download


◆『扉』 By 小池啓仁

Download


◆『For Me』By 小池啓仁

2009-07-11 EXCEL-VBAでアクティヴシートを制御する

以下は、アクティブシート上のセルを書き換えるタイミング(Worksheet_Change)で、

任意のシートにアクティブシートを切り替えて、そのシートでの処理を行い、

もとのシートをアクティブシートに戻します。


・サンプル
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Sheet_Work As Worksheet
Dim Sheet_Save As Worksheet

    Set Sheet_Save = ActiveSheet
    Set Sheet_Work = Worksheets("Sheet2")
    Sheet_Work.Activate
    
    '任意シート(例ではSheet2)の任意の処理を記述する。
    MsgBox "Sheet2"
    
    Sheet_Save.Activate
    Set Sheet_Work = Nothing
    Set Sheet_Save = Nothing
End Sub

ちなみに、Worksheet_Changeイベントは、セルの値が変更された時に発生しますが、SelectionChangeイベントは選択範囲が変わった時に発生します。

2009-07-10 とある退職送別会

今日は、帰社日で、その後、56歳のとある先輩の退職送別会がありました。

約34年のプログラマ生活に終止符を打ちました。当分は失業保険で暮らすとのことでした。


この先輩には、いろいろ教わりました。

私が、制御系から事務系に転向した平成元年あたり、コボルを先輩から教わり、先輩の消費税のロジックが凄かったことが記憶に残っています。

(実は、消費税の計算は大変なんですよ。単に5%を掛けるってもんじゃないです。請求単位、伝票単位、明細単位、内税、外税、税率変更、税率切り上げ、切り下げ、四捨五入・・・)


とりあえず、私は、60歳まではプログラマ生活を送りたいと思いました(あと6年)。

しかし、この大不況の中、開発の仕事ができることが、改めて有り難いと思いました。


今日は、送別会から帰ってきて、少し、以下の正規表現のブログを加筆修正しました。

最大マッチと最小マッチのところや、細かいところをいろいろと・・・。

2009-07-09 ブログ6月分をWebページへ

昨日は、私の誕生日で、家族のみんなで(長男除く)、夕食を『焼き肉のデン』で食べました。

お腹が一杯になったら、なぜか疲れがダーって感じで出てきて・・・家に帰ったら、お風呂に入って、すぐ寝てしまいました。(いつもなら、ネットを欠かさないのだけれど・・・)


ネタは、まだまだありますが、まとめる気力がなくなってしまって・・・、ペースを落として更新をしていきますね。

とりあえず、今日は、ブログ6月分をWebページへ変換しました。

2009-07-07 Perlの謎(番外編4):『ハッシュの配列』か『配列のハッシュ』か?

まず、以下のソースを見てください。

use strict;
use warnings;

my @aaa = ({xxx => 101, yyy => 102},
           {xxx => 201, yyy => 202});
print $aaa[0]{xxx}, "\n";
print $aaa[0]{yyy}, "\n";
print $aaa[1]{xxx}, "\n";
print $aaa[1]{yyy}, "\n";

上記のデータ構造は、『ハッシュの配列』でしょうか、それとも『配列のハッシュ』でしょうか・・・。


ラクダ本では、『ハッシュの配列』になっていました。

私は、約2年間ずーっと『配列のハッシュ』だと思っていました。だって、式と語順も一緒だし・・・。


昨日、読者の方からご指摘を受け、ラクダ本で調べたら、確かに『ハッシュの配列』と書かれていたのです!

『ハッシュの配列』は、英語で "arrays of hashes" です。だから、英語でも語順は一緒なのですね。


ofの意味は、「B of A」のとき、Aがまず存在していて、それに関係のあるBが存在していることを示している・・・とのことです。

まさに、hashesのデータがまず存在していて、それに関係のあるarraysが存在していることを示していますね。


しかしですね。たとえば、配列にデータが入っているとします。

このデータのことを『配列のデータ』といい、決して『データの配列』とはいいません。


上記のデータ構造は、配列に入っているデータが単にハッシュリファレンスになっているだけです。

なので、『配列のデータ』->『配列のハッシュリファレンス』->『配列のハッシュ』でいいわけです。

式と日本語の語順も一緒なので覚え易いわけです。


でも、ラクダ本が『ハッシュの配列』と云っている以上、逆らえないのですねこれが(^^;

ということで、本ブログと本サイトのコンテンツを見直して、ラクダ本にあわせて修正しました。


ご指摘して頂いた方、ありがとうございました。


2009-07-06 追記予定パート2

先日の『Perlの謎(その8):正規表現』へ以下を追記しました。

確認リンク:http://d.hatena.ne.jp/chaichanPaPa/20090704


以下は残件です。

2009-07-05 三鷹七中バスケット部ブロック準優勝!!

えーと今日、府中六中体育館で『夏の都大会』ブロック予選決勝戦がありました。

準決勝で三鷹三中を80対50で下し、宿敵府中六中と決勝戦へ・・・。


一時は3点差まで追い詰めましたが・・・力ひとつ及ばず、準優勝となりました!(ぱちぱち)。

『春の都大会』ブロック予選決勝の時よりは、府中六中を苦しめたことは確かです。

今度の都大会で再戦したらリベンジしないとね!


三男も体調が本調子でないなか、ふらふらよれよれになりながらも、よく頑張りました。

他の子達も皆、一所懸命で、汗だくで、それだけを見ていても感動的でした。


しかし、テクニック、スピード、パワーと実力はほぼ同じなのに、何が勝敗を決するのか・・・考えさせられた試合でもありました。

応援のお母さん方やお父さん達、お疲れ様でした。

はらはら、どきどきの決勝戦でしたね。

都大会が終わるまで、まだまだ子供への気使いが続きますね。頑張りましょう親も(^^;

2009-07-05 追記予定

昨日の『Perlの謎(その8):正規表現』への追記予定です。


他にも何かありますか?

2009-07-04 Perlの謎(その8):正規表現

今回の謎は、正規表現です。

はじめての人のために解説をしてみました。


他言語からの人は、正規表現を使う機会がなかったかもしれませんが・・・。

Perlでは、正規表現を使うための言語と言っても過言ではありません。

正規表現を使うことによりテキスト(文字列)編集処理が飛躍的に楽になるのです。


そもそも正規表現は、人体の神経回路網を数学的に説明するための方法として開発されました。その後、UNIXのケン・トンプソンによってコンピュータでの検索アルゴリズムに引き継がれました。ちなみに、正規表現を初めて使用したアプリケーションは、UNIX のエディタedやexの祖となったQEDというエディタのようです。QED、ed、grep等を経てPerlに引き継がれたようです。 (そもそもの正規表現は、参考リンクのリンク先を参照しました)


では、まずはじめにテストデータ、family.txt を用意します。

このテストデータを元にしてサンプルプログラムを踏まえて解説をしていきますね。


・family.txtファイルの内容
macha koike
yachu koike
chaichan koike
hiro koike
mama koike
papa koike
koike 6
ni-bo- horie yasashii
nee-nee horie chottokowai
60 horie
ma-kun murai
sachi murai
kazumasa murai
hisa

◆マッチング

まず始めに、苗字が『koike』の人をマッチさせてみましょう。(サンプル01 sample01.pl)

while($_ = <STDIN>){
   if($_ =~ /koike/){
      print $_;
   }
}

上記は、標準入力からデータを読み込んで一行づつループし、その行データに『koike』がマッチするか調べ、マッチした時に行データを標準出力しています。

『$_ =~ /koike/』の式はマッチした時は、真を返し、マッチしない時は、偽を返します。

では、実行してみましよう。

% test01.pl < family.txt
macha koike
yachu koike
chaichan koike
hiro koike
mama koike
papa koike
koike 6
・補足1

逆にマッチしない時は真を返し、マッチした時は偽を返すには『$_ !~ /koike/』とします。


◆アンカー

まずいことに、名前以外の koike 6 もマッチてしまいました。

そこで、koikeという文字列がデータの末尾に一致する場合のみに限定します。(サンプル02 sample02.pl)

while($_ = <STDIN>){
   if($_ =~ /koike$/){
      print $_;
   }
}

/koike$/の『$』は、文字列の末尾にマッチする記号で、アンカーと言います。

アンカーには、他に文字列の先頭にマッチする『^』と単語の境界(正確には、単語の先頭あるいは末尾)にマッチする『\b』、それ以外の部分にマッチする『\B』があります。

では、実行してみましよう。

% test02.pl < family.txt
macha koike
yachu koike
chaichan koike
hiro koike
mama koike
papa koike

今度は上手く行きました。


・アンカー『^』の検索(サンプル03 sample03.pl)

つぎに、アンカー『^』を使って『k』で始まる人を検索してみましょう

while(<STDIN>){
   if(/^k/){
      print;
   }
}

尚、『$_』は省略可能です。

% test03.pl < family.txt
koike 6
kazumasa murai

・補足2

また、アンカーには、 文字列の先頭にマッチする 『\A』 と文字列の末尾にマッチする 『\Z』 があります。

『\A』 と 『^』 、『\Z』 と 『$』 は機能がよく似ていますが、複数の行がある文字列を対象に正規表現を行った場合、『^』 は改行の直後にもマッチしますが、『\A』 は文字列の先頭にしかマッチしません。

また、『$』は改行の直前にもマッチしますが、『\Z』は文字列の末尾にしかマッチングしません。



◆文字クラス

また、よけいな koike 6 がマッチしてしまいました。

そこで、koike 6 には数字が入っていますので、数字があるとNGにすればいいわけです。

ですが、発想を変えて、数字以外の文字が連続するとしても同じです。


・数字以外の文字が連続の検索(サンプル04 sample04.pl)
while(<STDIN>){
   if(/^k[^0-9]+$/){
      print;
   }
}
% test04.pl < family.txt
kazumasa murai

今度は上手く行きました。

まず、[〜]は文字クラスといって、[0-9]の場合は 0から9までの1文字にマッチします。

[^0-9]は文字クラスの中に ^が付くことによって文字クラスの否定を意味します。

文字列のアンカーの『^』とは別物です。

[^0-9]+の+は1回以上の『繰り返し』という意味です。

つまり、0-9以外の一文字の繰り返しになります。

$は末尾にマッチのアンカーの$です。


・1語の名前を検索(サンプル05 sample05.pl)
while(<STDIN>){
   if(/^\S+$/){
      print;
   }
}
% test05.pl < family.txt
hisa

\Sも文字クラスで、空白文字以外を表します。

つまり、^\S+$ は先頭が空白文字以外で、これがかつ一回以上の繰り返しで、末尾までになります。


・3語の名前を検索(サンプル06 sample06.pl)
while(<STDIN>){
   if(/^\S+\s+\S+\s+\S+$/){
      print;
   }
}
% test06.pl < family.txt
ni-bo- horie yasashii
nee-nee horie chottokowai

\sも文字クラスで、空白文字(空白,タブ,改行)を表します。\Sの反対です。

つまり、^\S+\s+\S+\s+\S+$ は先頭が空白文字以外で、これがかつ一回以上の繰り返した後、空白文字を一回以上の繰り返し、空白文字以外一回以上の繰り返し、空白文字を一回以上の繰り返し、空白文字以外一回以上の繰り返しで、末尾までになります。


・文字クラス一覧
    [ABC]           A,B,Cのいずれか1文字    
    [A-Z]           A〜Zまでのいずれか1文字
    [A-Za-z0-9]     A〜Z, a〜z, 0-9までのいずれか1文字    
    [^ABC]          A,B.C以外の文字
    [^A-Z]          A〜Z以外の文字  
    \w              英数文字。[a-zA-Z0-9]と同様    
    \W              \w以外の文字
    \d              数値文字。[0-9]と同等    
    \D              \d以外の文字
    \s              空白文字(空白,タブ,改行)     
    \S              \s以外の文字
    \b              単語の区切り
    .               任意の一文字

・補足3

/koike/ だと koikesでもマッチしてしまいますが、/\bkoike\b/だと回避できます。

・補足4

\wと\Wは、アスキー系以外では機能しない場合があるらしい。




◆メタキャラクタとエスケープ

正規表現において特殊な意味を持つ文字をメタキャラクタと呼びます。

    + * ? . ( ) [ ] { } | \ $ ^

\は、メタキャラクタの本来の作用をエスケープし、

メタキャラクタ以外では書かないのと同じになります。

たとえば、


^\^ は、^という文字で始まる行にマッチ

\\ は、\自体にマッチ


また、\Qと\Eの間に挿入された文字列は全部の文字の前に \ が挿入されたものと同じです。

/\o\)\+\>/ と /\Qo)+<\E/ は同じ。


◆繰り返し
    A+              1個以上連続したA(A, AA, AAA, ...)
    A*              0個以上連続したA(  , A, AA, AAA, ...)
    A?              0または1つの任意文字(  , A, B, C, ...)
    A{5}            5回繰り返し。 AAAAAと同じ
    A{3,}           3回以上繰り返し。 AAA+と同じ
    A{3,5}          3回以上5回以下繰り返し。 AAAA?A?と同じ

◆ 最大マッチと最小マッチ

たとえば、以下のようなデータがあったとします。

<h1>Koike family</h1> <h2>Home Page</h2> <h3>By chaichanpapa</h3>

このデータからタグのみ除去してみましょう。

タグは < ではじまり、 > で終わる文字列です。

その文字列の中を「.」の任意の一文字で「*」で0回以上の繰り返しとして指定します。

ですので、以下のようなプログラムになります。

・サンプル(sample10.pl)
while(<DATA>){
      s/<.*>//g;
      print;
}
__END__
<h1>Koike family</h1> <h2>Home Page</h2> <h3>By chaichanpapa</h3>

では、実行してみましょう。

% sample10.pl

%

改行のみの表示だけになってしまいました。

実は、perlでは、パターンマッチがもっとも長い文字列とマッチする最大マッチなのです。

ですから、<h1>Koike から chaichanpapa</h3> まで削除されてしまいました。

では、タグのみ削除するにはどうしたらいいでしょう?

それには最小マッチの ? を指定します。

・サンプル(sample11.pl)
while(<DATA>){
      s/<.*?>//g;
      print;
}
__END__
<h1>Koike family</h1> <h2>Home Page</h2> <h3>By chaichanpapa</h3>

では、実行してみましょう。

% sample11.pl
Koike family Home Page By chaichanpapa

今度は、タグが除去され、上手くいきました。


・補足5

最大マッチと最小マッチは、英語(perlretut.pod)での"maximal match"と"minimal match"の訳です。

しかし、訳者によって、最長マッチと最短マッチや最多マッチと最少マッチになっていますね。

ちなみに、私は、すP派です。


◆グループ化と選択

文字列を繰り返すときは()を使ってグループ化します。

    koi(ke)+        koike, koikeke, koikekekeなどにマッチします。
     
    いくつかのパターンのどれかにマッチさせるときは | を使います。
    (選択はパフォーマンスがあまり良くないとのことです。)

    macha|yachu     machaかyachuにマッチします。
    koike(X|Y)      koikeXかkoikeYにマッチします。

◆カッコを使った記憶

また、グループ化した部分は後から参照することができます。

これを後方参照といい、 同じ正規表現内で後方参照を行うには、\1, \2... を用います。

    /(koike)\1/    koikeが2回連続する文字列にマッチします。

また、正規表現外で後方参照を行うには、マッチ特殊変数 $1, $2... を用います。

$str =~ /^(k.+) (c.*)$/i;
print $1, "\n"; # koikeと表示される
print $2, "\n"; # chaichanと表示される

◆マッチ特殊変数

マッチ特殊変数には、$1,$2,・・・の他に、$` , $& , $'等があります。

これらは、パターンマッチしたときに「マッチする前までの文字列」、「マッチした文字列」、「マッチした後の文字列」が各々、$` , $& , $' に格納されます。では、プログラムで確かめてみましょう。


サンプル sample14.pl
  $n = 0;
  while(<STDIN>){
        chomp;
        / \S+ | /;
        ++$n;
        print "*** $n ***\n";
        print "AAA: $`\n";
        if($& ne " "){
           print "BBB:" . substr($&, 1, length($&) -2) . "\n";
        } 
        print "CCC: $'\n";
        print "\n";
  }
% cat family3.txt
macha koike
sayuri koike chaichan
%
%
% sample14.pl < family3.txt
*** 1 ***
AAA:macha
CCC:koike

*** 2 ***
AAA:sayuri
BBB:koike
CCC:chaichan

まず、chompは $_ の末尾の改行コードを切り落とします。

/ \S+ | /; は「左右に空白を持つ非空白1文字以上か、または、1文字の空白」のマッチです。

つまり、今回の場合は、 *** 1 ***は「1文字の空白」のマッチで、 *** 2 ***は「左右に空白を持つ非空白1文字以上か」にマッチします。

そして、$` と $& と $' に各々の値が格納されます。尚、$&には前後にスペースが入っていますので、substr($&, 1, length($&) -2)で削除します。


◆置換処理

置換演算子(s///)を用いると、文字列の置換を行うことができます。

my $str = 'koike sayuri';
$str =~ s/(koike) sayuri/$1 chaichan/; # $strは 'koike chaichan' になる
print $str, "\n";

・修飾子

以下の修飾子を指定することにより、パターンマッチの振る舞いを変えることができます。

・i修飾子

i修飾子は、正規表現がアルファベットの大文字小文字を区別せずにマッチするようにするために指定します。

m/^chaichan$/i; # chaichanにもChaichanにもCHAICHANにもChAichanにもマッチする。

・s修飾子
#「.」が改行にもマッチするようになる
my $str = "aaa bbb\nccc ddd";
print "No Match1\n" if ($str !~ /bbb.*ccc/);
print "Match1\n"    if ($str =~ /bbb.*ccc/s);

・m修飾子
my $str = "aaa bbb\nccc ddd";
print "No Match2\n" if ($str !~ /^ccc/);
print "Match2\n"    if ($str =~ /^ccc/m);

・x修飾子

正規表現内の空白や改行が無視され、「#」以降はコメントとして扱われます。

# 1と出力
print 1 if 'Chaichan' =~ /
C
h
a
i
# コメント
c
h
a
n
/x;

・e修飾子

以下はあまり意味がないプログラムですが、3回『e』しています。

my $str = "hello world";
$str =~ s/\w+/subx()/eeeg;
print $str;

sub subx {
    return 'suby()';
}
sub suby {
    return 'subz($&)';
}
sub subz {
    ucfirst($_[0]);
}

C:\perltest>perl reg_e.pl
Hello World

・g修飾子

連続して何回もマッチ gですが、上記で『s/\w+/subx()/eeeg』を『s/\w+/subx()/eee』にすると、表示は『Hello world』となり、worldはそのままで、Helloだけ『h』が『H』になり、連続しなくなります。

逆にいうと、g修飾子を指定すると連続して何回もマッチするわけです。


・o修飾子

変数展開が最初の1回だけ行われます。

逆にいうと、o修飾子を指定しない場合は、毎回変数展開される。

my $str = "aaa bbb\nccc ddd";
my $regex = 'aaa';
for (1..10) {
    print "Match3\n" if ($str =~ /$regex/o);
}

◆拡張構文

Perlには、以下のような拡張構文があります。

拡張構文は、キャプチャ(カッコを使った記憶)を行わないため、マッチした部分を正規表現の中で\1、\2のように参照したり、後から$1、$2のような変数で参照したりすることができません。


以下は、拡張構文のサンプルです。すべてマッチします。

$bbb = '東京都庁';
$ccc = 'とうきょう都庁';
print "Match1", "\n" if ($bbb =~ /東京(?=都庁)/);  # 東京の後に都庁が続いている東京にマッチ
print "Match2", "\n" if ($bbb =~ /東京(?!議会)/);  # 東京の後に議会が続いていない東京にマッチ
print "Match3", "\n" if ($bbb =~ /(?<=東京)都庁/); # 東京の後に都庁が続いている都庁にマッチ
print "Match4", "\n" if ($ccc =~ /(?<!東京)都庁/); # 東京でないの後に都庁が続いている都庁にマッチ

ちなみに、拡張構文の「東京(?=都庁)」と普通構文の「東京(都庁)」は同じ結果になりますが、すべての拡張構文には後方参照がありません。

また、拡張構文では検索文字にパターンマッチ修飾子(imsx)が埋め込めます。

# 普通構文
$ddd = 'Tokyo';
if (/$ddd/i) {
  print "$ddd\n";
}
# 拡張構文
$ddd = "(?i)Tokyo";
if (/$ddd/) {
  print "$ddd\n";
}
◆ 正規表現初心者卒業

上記がマスター出来たら、とりあえず、正規表現初心者卒業です。

しかし、正規表現は奥が深く、また、Perlが独自に拡張しています。

ですので、まだまだ、正規表現を極めようという人は、とりあえず以下で勉強をしてみてください。

再帰的な正規表現や正規表現の中にPerlコードを記述できたりと、高度なテクニックが書いてありますよ。


◆ 参考リンク

2009-07-03 セルの入力チェックで変更前の値に戻すのは

VBAでセル毎の入力チェックをする時は、普通、Worksheet_Changeサブルーチンにて行います。

Worksheet_Changeサブルーチンには、VB本体からTargetオブジェクトが渡されます。

Targetオブジェクトは、変更後のデータになっています。

変更後のデータをチェックして、何かのエラーの場合は、変更前の値に戻したいケースが多々ありますね。

しかし、Targetオブジェクトには、変更前のデータがないのです(探しまくったがみつからない)。

さぁー、こまった!


ここで、発想を変えて、Undoすればいいのではないか・・・と思いつく!

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Value = "666" Then '何かのエラーの場合(例では666が入力されたとき)
       Application.Undo          '変更前の値に戻にもどす
    End If
End Sub

いや・・・、実は、これを編み出すのに結構時間が掛かってしまった。

Targetオブジェクトの中に変更前の値があるのかを探しまくり、ネットで変更前の値の求め方を探しまくり、結局見つからず・・・。

天の啓示、Undoが閃いたのでした(パチパチ)

2009-07-02 資本主義崩壊の首謀者たち

資本主義崩壊の首謀者たち (集英社新書 489A)

とにかく、一気に読みました。

ユダヤ系金融の系統が複雑すぎて、ちゃんと読まないと理解できないところもありますが、資本主義崩壊の首謀者はユダヤ系の人々ですね。


この本を読むとアメリカは、すでに資本主義が崩壊(GM国営化等)して、働かず贅沢して借金、ドル札はただの紙切れとなり、そんなアメリカ国債を溜め込んでいる日本は、アメリカから振り込め詐欺を受けているようなものと著者は言う。


また、2010年までに「ゆうちょ銀行」と「かんぽ生命」が株式上場されたら、根こそぎ外国人投資家に持っていかれると著者は言う。


とにかく、働かず贅沢して借金のアメリカには、一切金融支援しない態度を日本が貫いていかないと、日本は大変なことになると著者は言っています。


もうちょっと、じっくり読んで、首謀者達の騙しの手口を理解したい・・・。

2009-07-01 祝!!三鷹七中バスケット部『夏の都大会』出場決定!

三鷹七中バスケット部は、先日、明大明治中学校体育館で準々決勝があり、府中九中を破り、9ブロックベスト4になり、『夏の都大会』出場を決めました(パチパチ)!

これで、『新人戦』、『春の大会』と3回連続の都大会出場です。


長男の時代、次男の時代と、寸前までいって敗れ去った都大会出場を3回も突破したとは、三男は運がいい。

『春の大会』からスランプだった三男もここにきて、体調がよくなってきたし、また、みんなぼーずで気合いを入れたし、今回の『夏の都大会』は、奇跡が起こるかも!


とりあえず、残りの予選の準決勝で、宿命のライバル三鷹三中と雌雄を決し、決勝では、府中六中(たぶん)に春のリベンジをしないとね。

今回の三鷹七中は、いろいろあって、チームの絆が強くなっているから、手強いぞ!

2009-07-01 Perlの謎(その7):マッチ演算子の区切り文字

マッチ演算子はスカラー変数に格納されている文字列を正規表現を使ってマッチするか判断する演算子です。

通常、区切り文字『/』を使って以下のようになります。

if ($_ =~ m/abc/) {
   print "マッチした! \n"; 
}
else {
   print "マッチしない!\n"; 
}

しかし、以下のようにも書けるのです。

if (m@abc@) {
   print "マッチした! \n"; 
}
else {
   print "マッチしない!\n"; 
}

そう区切り文字は、『/』でなくとも、任意の非英数字(空白文字は除く)でも大丈夫なのです。

またしかし、非英数字でもカッコ系は、開き/閉じのペアでないとなりません。

またまたしかし、以下の3つに関しては、注意が必要です。

  1. 『#』を使う場合は、マッチ演算子との間にスペースを入れないこと(入れるとコメント認識される)。
  2. 『'』を使う場合は、パターン内で変数が展開されなくなる。
  3. 『?』を使う場合は、??演算子になる(1回しかマッチしない)

ただし、区切り文字『/』は、他の非英数字と違い、mを省略できます。

if (/abc/) {
   print "マッチした! \n"; 
}
else {
   print "マッチしない!\n"; 
}

◆サンプル(m.pl)
use strict;
use warnings;

my $s = "abcxxxxabcyyyyabczzzz";
if ($s =~ m/abc/) {
   print "マッチした! \n"; 
}
else {
   print "マッチしない!\n"; 
}
if ($s =~ m@abc@) {
   print "マッチした! \n"; 
}
else {
   print "マッチしない!\n"; 
}
if ($s =~ m<abc>) {
   print "マッチした! \n"; 
}
else {
   print "マッチしない!\n"; 
}

my $a = 0;
while($s =~ m/abc/g) {
   $a++;
}
print $a, "\n";

$a = 0;
while($s =~ m?abc?) {
   $a++;
}
print $a, "\n";

◆実行結果
C:\perltest>perl m.pl
マッチした!
マッチした!
マッチした!
3
1