Perlのキモ

  1. localとmyの意味
  2. 正規表現のキモ

localとmyの意味

→ TOP
Perlにおけるlocal宣言は、C++等でいうところのいわゆる「ローカル変数」ではなく、グローバル変数をスコープ内で一時的に書き換えるものです。世間一般にいうところのローカル変数にはmy宣言が相当します。

具体例を挙げますと、

$text = "GLOBAL" ;
TEST1:{
	my ($text) = "MY" ;
	print "$text / $main::text \n" ;
}
TEST2:{
	local ($text) = "LOCAL" ;
	print "$text / $main::text \n" ;
}
print "$text / $main::text \n" ;

このスクリプトの出力結果は、
MY / GLOBAL
LOCAL / LOCAL
GLOBAL / GLOBAL
となります。$main::textとして、明示的にグローバル変数としての$textを指定しているにも関わらず、TEST2における出力では$main::textもlocalとして再定義した値 "LOCAL" になっているのが分かります。スコープTEST2を抜けた後は、$textの値は再び "GLOBAL" に戻っています。

このように、my宣言した変数は純粋にスコープの中でのみ有効な「ローカル変数」であるのに対し、local宣言した変数は同名のグローバル変数の値をスコープ内にいる間一時的に書き換えます。ですので、純粋な意味でのローカル変数として扱いたい場合にはlocalではなくmyを使うようにするのが無難です。例えば、以下の様なスクリプトで、

$text = "GLOBAL" ;
sub SUB1{
	print $text ;
}

sub SUB2{
	local ($text) = "TEMPORARY" ;
	・
	・
	・
	&SUB1 ;
}

もし「グローバルな$textの値を表示する」という動作を期待してSUB1を定義していた場合、SUB2内で一時的に利用するつもりで$textをlocal宣言してしまうと、その後SUB2内からSUB1を呼び出しているところでは期待する "GLOBAL" ではなく "TEMPORARY"が表示されてしまいます。無論この性質を逆手に取る使い方もありますが(特殊変数を書き換えたりする場合など: $_ をlocalで書き換えるという使い方はよく使われる)、基本的には「ローカル変数はmyとして宣言する」という方針を貫いた方がバグも出現しにくくなるでしょう。


正規表現のキモ

→ TOP
Perlの強力な文字列処理の要と言える正規表現。しかし、実際のところ正規表現の見た目は呪文の様であり、何をやってるかよく分からない、やりたいことをどう書いたら良いか分からない、という人も多いでしょう。そこで、正規表現の構造を分かりやすく説明し、「こんなことをしたい場合にはどう書いたら良いのか」というケーススタディを通して正規表現を勉強してみようと思います。

正規表現中に出てくる最も基本的な要素は、
  1. 文字の種類を表すもの
  2. 文字の量を表すもの
の二つです。つまり「どんな文字が」「どれだけ並んでいるか」というのが基本単位であり、それの組み合わせ及びその他の修飾要素によって正規表現は構成されています。まずこの二つをちゃんと理解しなければなりませんし、それさえ理解してしまえば後はすんなり使いこなせるようになるでしょう。


【文字の量を表すもの】

順番は逆になりますが、文字の量を表すものからまず見て行きましょう。なぜこちらからかというと、それはバリエーションが少ないから説明がし易いからです(笑)。以下の6パターンしかありません。これらは全て「その直前の文字がどれだけの量出現するか」を修飾します。

*0回以上出現する
+1回以上出現する
?1回または0回出現する
{n}ちょうどn回出現する
{n,}n回以上出現する
{n,m}n回以上m回未満出現する

正確に言えば、「何も指定がない場合」の「ちょうど1回出現する」というパターンもありますが、これは説明するまでもないでしょう。さて、それでは実例を挙げてみましょう。

/ab*c/ 「ac」「abc」「abbbbbbbc」等、aとcの間にbが0回以上出現するパターンにマッチ
/ULY+!/ 「ULY!」「ULYYYYYYY!」等、ULと!の間にYが1回以上出現するパターンにマッチ。DIOの叫びを検出したい時などに。
/COLOU?R/ 「COLOR」又は「COLOUR」にマッチ。
/ULY{5,15}!/ 「ULYY!」や「ULYYYYYYYYYYYYYYYYYYYYYYYYYY!」はDIOの叫びとして短すぎる/長すぎると思う場合に。

使い方の感じはお分かり頂けたでしょうか。ただ、ここまでの説明だと「 {n} 」の使い道がないじゃないか、と思われるかも知れません。「 /x{3}/ 」は「 /xxx/ 」と書けば済むことですからね。
そこで、以下に説明する「文字の種類を表すもの」が必要になってくるわけです。


【文字の種類を表すもの】

文字の種類を表すものの代表的な例は、当たり前ですが文字そのものです。例えば、「 /abc/ 」という正規表現は「文字列中のabcの部分」にマッチします。それ以上でもそれ以下でもありません。
そこで、「この文字とこの文字のどれか」「文字なら何でも」といった具合に種類を指定する方法があるわけです。実は、これらのパターンは「文字の量を表すもの」以上に少なくて、実のところ4パターンしかありません。ただバリエーションに富んでいるだけです。以下の通りです。

. (ピリオド)改行以外の文字なら何でも
[][]内に書かれた文字のどれか
[^][^]内に書かれた文字以外のどれか
\s、\w等のメタ文字「\」+「英数字」という形式で、ある特定の文字の範囲や通常表記できない文字を表すものがあり、それらをメタ文字と呼ぶ。\n→改行、\t→タブ、\d→数字(0〜9)、といった具合。

. (ピリオド)は、「改行文字以外なら何でもOK」というジョーカーの様な文字です。例えば「 /c..y/」という正規表現だったら、「caty」や「cosy」等にマッチします。後述する[^]を用いた「 [^\n] 」というパターンの略式表記である、と言い換えても良いでしょう。


【ケーススタディ】

「FONTタグを取り除く」

文字列に含まれるFONTタグを全て取り除くことを考えてみましょう。
まず、FONTタグの構造を考えると、
・<FONT PARAM1=VALUE1 PARAM2=VALUE2 .. PARAMn=VALUEn>
・</FONT>
の二つであることは分かりますね。これを頭から解析してゆきます。

まず、先頭が < であるのは共通です。ですのでまず
s/<//
となりますね。

次に、「<FONT」である場合と「</FONT」である場合がありますので、「/が0または1回出現した後にFONTという文字が続く」ことになります。よって、ここまでは
s/<\/?FONT//
となります。

さて、閉じタグの場合はこの直後に > が来ますが、開く方はsizeやらcolorやらのパラメタが並びます。よって、「>まで任意の文字が0個以上出現する」と考えられますから、
s/<\/?FONT.*>//
ということになるでしょう。

ただ、場合によってはひとつのタグのパラメタが複数行に渡って書いてあったりすることがあります。「 . 」は改行文字にはマッチしませんから、
<FONT SIZE=2
      COLOR="#FF0000">
といった書き方をされている場合困ってしまいます。
そこで、「>まで任意の文字」ということは「任意の文字には>は含まれない」ということであることを利用して、
s/<\/?FONT[^>]*>//
このように書きます。これで大丈夫でしょう。おっと、<FONT>だけじゃなく<font>にもマッチしてもらわないと困るので、「大文字小文字関係なし」の修飾子をつけ、「全て取り除く」ために「複数回マッチ」の修飾子も付けて、
s/<\/?FONT[^>]*>//ig
これで完成です。


→ TOP