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

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

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

  • \" ダブルクォーテーション( " )のエスケープ
  • \$ ダラー( $ )のエスケープ
  • \\ エスケープのエスケープ
  • \@ アットマーク( @ )のエスケープ
  • \% パーセント( % )のエスケープ
  • \; セミコロン( ; )のエスケープ

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

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

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

  • \t タブ
  • \n 改行
  • \r リターン
  • \f 改ページ
  • \b バックスペース
  • \a アラーム
  • \e エスケープ
  • \003 8進数
  • \x1b 16進数
  • \cC CTRL-C
  • \l 次の文字を小文字
  • \u 次の文字を大文字
  • \L \E が来るまで小文字
  • \U \E が来るまで大文字
  • \Q \E が来るまで非英数字の前に \ を追加
  • \E \L、\U、\Qの効果を終了する

民主圧勝

夕方7時過ぎにママと一緒に都議選の投票に行ってきました。
現在22:30頃、民主の圧勝ですね。


自民の菅(すが)氏が都議選寸前まで民主の鳩山さんをイジメていたのが裏目にでましたね。
菅氏、小沢氏もイジメていたので、民主が天下をとったら、オモシロイことになりますね。


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


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

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

えーと今日は、毎年恒例のお盆の式典が某教会でありました。
毎年恒例だと、本当に一年があっという間に過ぎてしまうというように感じる歳になりました。
とりあえず以下は、過去に書いた盂蘭盆会のブログです。

今回は、教育評論家の川越淑江さんのご講演がありました。
期待しないで聞いていた割りには、結構良い話が聞けました。


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


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

  • オアシスのオは、『おはようございます』という素直な心
  • オアシスのアは、『ありがとうございます』という感謝の心
  • オアシスのシは、『親切』という思いやる心
  • オアシスのスは、『すみません』という反省する心

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


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

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イベントは選択範囲が変わった時に発生します。

とある退職送別会

今日は、帰社日で、その後、56歳のとある先輩の退職送別会がありました。
約34年のプログラマ生活に終止符を打ちました。当分は失業保険で暮らすとのことでした。


この先輩には、いろいろ教わりました。
私が、制御系から事務系に転向した平成元年あたり、コボルを先輩から教わり、先輩の消費税のロジックが凄かったことが記憶に残っています。
(実は、消費税の計算は大変なんですよ。単に5%を掛けるってもんじゃないです。請求単位、伝票単位、明細単位、内税、外税、税率変更、税率切り上げ、切り下げ、四捨五入・・・)


とりあえず、私は、60歳まではプログラマ生活を送りたいと思いました(あと6年)。
しかし、この大不況の中、開発の仕事ができることが、改めて有り難いと思いました。


今日は、送別会から帰ってきて、少し、以下の正規表現のブログを加筆修正しました。
最大マッチと最小マッチのところや、細かいところをいろいろと・・・。

ブログ6月分をWebページへ

昨日は、私の誕生日で、家族のみんなで(長男除く)、夕食を『焼き肉のデン』で食べました。
お腹が一杯になったら、なぜか疲れがダーって感じで出てきて・・・家に帰ったら、お風呂に入って、すぐ寝てしまいました。(いつもなら、ネットを欠かさないのだけれど・・・)


ネタは、まだまだありますが、まとめる気力がなくなってしまって・・・、ペースを落として更新をしていきますね。
とりあえず、今日は、ブログ6月分をWebページへ変換しました。

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が存在していることを示していますね。


しかしですね。たとえば、配列にデータが入っているとします。
このデータのことを『配列のデータ』といい、決して『データの配列』とはいいません。


上記のデータ構造は、配列に入っているデータが単にハッシュリファレンスになっているだけです。
なので、『配列のデータ』->『配列のハッシュリファレンス』->『配列のハッシュ』でいいわけです。
式と日本語の語順も一緒なので覚え易いわけです。


でも、ラクダ本が『ハッシュの配列』と云っている以上、逆らえないのですねこれが(^^;
ということで、本ブログと本サイトのコンテンツを見直して、ラクダ本にあわせて修正しました。


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


プログラミングPerl〈VOLUME1〉

プログラミングPerl〈VOLUME1〉

追記予定パート2

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

  • 説明していないマッチ変数($& $` $')
  • \Aと\Zアンカー(常に文字列の先頭と末尾にのみマッチ)

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


以下は残件です。

  • 最大マッチと最小マッチについて
  • 説明していない修飾子(s m o)

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

えーと今日、府中六中体育館で『夏の都大会』ブロック予選決勝戦がありました。
準決勝で三鷹三中を80対50で下し、宿敵府中六中と決勝戦へ・・・。


一時は3点差まで追い詰めましたが・・・力ひとつ及ばず、準優勝となりました!(ぱちぱち)。
『春の都大会』ブロック予選決勝の時よりは、府中六中を苦しめたことは確かです。
今度の都大会で再戦したらリベンジしないとね!


三男も体調が本調子でないなか、ふらふらよれよれになりながらも、よく頑張りました。
他の子達も皆、一所懸命で、汗だくで、それだけを見ていても感動的でした。


しかし、テクニック、スピード、パワーと実力はほぼ同じなのに、何が勝敗を決するのか・・・考えさせられた試合でもありました。
応援のお母さん方やお父さん達、お疲れ様でした。
はらはら、どきどきの決勝戦でしたね。
都大会が終わるまで、まだまだ子供への気使いが続きますね。頑張りましょう親も(^^;

追記予定

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

  • 最大マッチと最小マッチについて
  • 説明していない修飾子(s m o)
  • 説明していないマッチ変数($& $` $')
  • \Aと\Zアンカー(常に文字列の先頭と末尾にのみマッチ)


他にも何かありますか?

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/』の式はマッチした時は、真を返し、マッチしない時は、偽を返します。
では、実行してみましよう。

% sample01.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』があります。
では、実行してみましよう。

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

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

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

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

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

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

% sample03.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;
   }
}
% sample04.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;
   }
}
% sample05.pl < family.txt
hisa

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

・3語の名前を検索(サンプル06 sample06.pl)
while(<STDIN>){
   if(/^\S+\s+\S+\s+\S+$/){
      print;
   }
}
% sample06.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 = 'koike chaichan';
$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 大文字小文字の同一視 (case-insensitive)
  • s 「.」が改行にもマッチするようにする (single line)
  • m 複数行として扱う (multi-line)
  • x 拡張正規表現を使う (extended)
  • e Perlのコードとして評価する (evaluation)(並べてた数だけevalします)
  • g 連続して何回もマッチ (global)
  • o 一度だけコンパイルする (only once)
・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修飾子
#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のような変数で参照したりすることができません。

  • (?# コメント) 正規表現内にコメントを入れます。
  • (?=式) 前方一致検索です。
  • (?!式) 後続の文字列が式に一致しなければマッチします。
  • (?ismx) 正規表現内にパターンマッチ修飾子を埋めみます。
  • (?<=式) 後方一致検索で先行する文字列が式に一致すればマッチします。
  • (?<!式) 後方一致検索の否定形で先行する文字列が式に一致しなければマッチします。


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

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

ちなみに、拡張構文の「東京(?=都庁)」と普通構文の「東京(都庁)」は同じ結果になりますが、すべての拡張構文には後方参照がありません。
また、拡張構文では検索文字にパターンマッチ修飾子(imsx)が埋め込めます。

$_ = 'TOKYO';
# 普通構文
$ddd = 'Tokyo';
if (/$ddd/i) {
  print "$ddd\n";
}
# 拡張構文
$ddd = "(?i)Tokyo";
if (/$ddd/) {
  print "$ddd\n";
}

正規表現初心者卒業

上記がマスター出来たら、とりあえず、正規表現初心者卒業です。
しかし、正規表現は奥が深く、また、Perlが独自に拡張しています。
ですので、まだまだ、正規表現を極めようという人は、とりあえず以下で勉強をしてみてください。
再帰的な正規表現正規表現の中にPerlコードを記述できたりと、高度なテクニックが書いてありますよ。

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

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が閃いたのでした(パチパチ)

資本主義崩壊の首謀者たち

資本主義崩壊の首謀者たち (集英社新書 489A)
とにかく、一気に読みました。
ユダヤ系金融の系統が複雑すぎて、ちゃんと読まないと理解できないところもありますが、資本主義崩壊の首謀者はユダヤ系の人々ですね。


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


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


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


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

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

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


長男の時代、次男の時代と、寸前までいって敗れ去った都大会出場を3回も突破したとは、三男は運がいい。
『春の大会』からスランプだった三男もここにきて、体調がよくなってきたし、また、みんなぼーずで気合いを入れたし、今回の『夏の都大会』は、奇跡が起こるかも!


とりあえず、残りの予選の準決勝で、宿命のライバル三鷹三中と雌雄を決し、決勝では、府中六中(たぶん)に春のリベンジをしないとね。
今回の三鷹七中は、いろいろあって、チームの絆が強くなっているから、手強いぞ!