Perl+CGI


Perl+CGI-room

CGIのmodulesドキュメント

Perl_modules

  • root権限が必要jcode.plはひと昔
    • Jcode.pmの組み込み
      perl -MCPAN -e shell
      cpan> install Jcode
  • 次にCGI_modules
    • CGI.pmの組み込み
      perl -MCPAN -e shell
      cpan> install CGI

pmを使う

use CGI;
  • useを使って組み込まれたモジュール(.pm)は、package 宣言された「クラス」です
  • 実体を宣言
    • CGIモジュールを宣言し、オブジェクトを$cgiに代入する。
      $cgi = new CGI;
  • newはコンストラクタと呼ばれ、このクラスの実体を生成する関数です。javaとPerlではnew()という関数名がコンストラクタとして使われます。したがって、以下は同じ意味になります。
$cgi = CGI::new(); 
  • CGI::new();は、「CGIというクラスのnew()という関数を呼び出す」という意味です。結果としてオブジェクトが返ります。
  • 例)フォームから入力されたpasswdの値を取り出す
    $your_name = $cgi->param("passwd");
  • つまり、cgi->param('passwd')は、cgiというオブジェクトの中の、param()という関数(メゾット)、という意味です。

正規表現初歩

  • 正規表現とは、文字列を、文字列の並びの規則(パターン)で表現したものです。
  • たとえば、0123456789を正規表現で表すと、0-9となります。同様に、abcdefg…zを正規表現で表すと、a-zとなります。
  • もし正規表現を使わずに、aまたはbまたはcまたはdまたはeまたはf、を判別したい場合、
if ($a eq "a" || $a eq "b" || $a eq "c" || $a eq "d" || $a eq "e" || $a eq "f")
  • というふうに、||で繋いで条件文を全部書かねばなりません。これが、aからfまでだからいいですが、aからzまでのどれかだとしたら、aからzまでを||で結んで条件文を書く必要がでてきます。(もっとも、その方がプログラムの可読性はよくなります)
  • しかし、これを、正規表現で表すと、
if ($a=~/[a-f]/) {
  • という風に表せます。したがって、aからzまででも、[a-z]という風に表す事ができます。
$aは[a-g]にマッチするので、machi!!と表示される。
$a="c";
if ($a=~/[a-g]/) {
print "machi!!\n";
} else {
print "no machi!!\n";
} 
  • ここでは、aという変数を使いましたが、Perlでは全般的に_という変数名を使うことによって、変数名を省略することができます。$_は組み込み変数ですが説明はしません。
$a=~を省略した場合、暗黙に$_という変数名が対象になる。
$_="c";
if (/[a-g]/) {
print "machi!!\n";
} else {
print "no machi!!\n";
} 

正規表現で使われる特殊文字

  • 改行コード以外の任意の1文字にマッチします。
a.
  • は、a1でもa2でもaaでもマッチします。aのあとに改行コード(\n)がきていたらマッチしません。
  • 正規表現で使う文字そのものを使いたい時に使います。たとえば、\.はピリオドそのものにマッチします。
a\.
  • は、a.という文字にだけマッチします。
  • 「先頭に」という意味です。したがって、
^abc
  • は、abcdefgという文字列はマッチします。zzzzabcdefgという文字列はマッチしません。
  • 「最後に」という意味です。
abc$
  • は、zzzzzabcという文字列はマッチします。abczzzzという文字列はマッチしません。
[ ] 
  • この[ ]で囲まれた中にある文字のどれかが含まれる、という意味です。
[abcde]は、aかbかcかdかeがマッチします。
[a-z]は、aかbかcか……zがマッチします。
[0-9a-z]は、0から9までの数字か、aからzまでのアルファベットがマッチします。
| 
  • 「または」という意味です。複数の条件のいずれかにマッチさせたい時に使います。 abcdefg | 123456 は、abcdefgまたは123456という文字列がマッチします。
[^] 
  • 「以外の」という意味です。
  • [^a-z]は、abcdefg……z以外の文字、という意味です。

量指定子

  • 直前の文字が何個つづいているか、という事を指定する記号です。
  • 直前の文字0回以上の繰り返しにマッチします。
a*
  • は、aaaaaaaa という風にaがいくつ続いてもマッチしますし、aという文字がなくてもマッチします。
  • 直前の文字の1回以上の繰り返しにマッチします。*との違いは、0回ではいけないという事です。つまり、少なくともaという文字が1回以上出現しないとマッチしません。
  • 0回、1回の繰り返しにマッチします。つまり、

a?

は、aという文字1回にマッチしますし、aという文字自体がなくてもマッチします。

{ } 
  • 繰り返しの数を指定できます。
  • a{2}は、aaにマッチします。
  • a{2,]は2回以上の繰り返しにマッチします。つまり、aはマッチしませんが、aaやaaaはマッチします。
  • a{2,3}は、2回以上3回以内の繰り返しにマッチします。つまり、aaと、aaaはマッチしますが、それ以上aがつづいても4文字目以降のaにはマッチしません。
  • {0,}は*、{1,}は+、{0,1}は?と同じ意味です。

よく使うパターン

\w 
  • [0-9a-zA-Z_]と同じで、任意の数字または英文字またはアンダーバーという意味です。
\W 
  • 大文字の\Wは、小文字の\w以外という意味です。
\d 
  • [0-9]と同じで、数字という意味です。
\D 
  • 大文字の\Dは数字以外という意味です。
\s 
  • [ \t\r\n\f]と同じで、スペース・タブ・改行・改ページのうちのどれか、という意味です。
\S 
  • 大文字の\Sは、小文字の\s以外という意味です。

正規表現を使った文字の分解

  • たとえば、スペースで区切ってある文字列があったとします。区切りの文字の文字数はわからず、とにかく連続したスペースはすべて区切りとみなしたい場合があります。この場合、
$_="aaaa    bbb cc   dddddd ";
@datas=split(/\s+/);
  • という風に、split関数の中で正規表現を使えば、1個以上の空白文字を区切りとして配列変数に格納する事ができます。
  • この場合、
    $datas[0]には、 aaaa
    $datas[1]には、 bbb
    $datas[2]には、 cc
    $datas[3]には、dddddd

正規表現を使った文字列の置換

  • フォーマットが可変長の文字列から、数字の部分だけを取り出したい場合を考えます。
  • たとえば、「cyborg009」という文字列だった場合は「009」の部分だけを取り出したい場合。ただし、cyborgの部分は固定ではなく、長さが決まっていないとします。
  • この場合、数字の部分だけをマッチさせたいわけです。[0-9]と書いてもいいのですが、前述の通り、数字は\dでも良かったですよね。また、単に数字ではなく、「数字が1個以上連続している部分を取り出す」わけですから、+記号を足して\d+となります。
/\d+/
  • とすることで、「変数_の中から、数字が連続している部分をマッチさせて、結果を&に入れる」という意味になります。
  • Perlでは、特に指定しないと暗黙で使われる変数があり、その代表的なものが_です。「対象となる変数名が省略された場合には変数_を使う」という事がしばしばあります。
  • また$&は、直前のパターンマッチでマッチした部分が自動的に入ります。この場合は\d+なので、数字が連続している部分が入ります。
  • 次に、取り出した文字列を加工してみましょう。ここでは、とりあえず「1を足す」という風にします。
$&+1
  • とすることで、009+1で、10となります。
  • また、桁数もそろえることにします。length($&)で、マッチした部分の桁数がわかりますから、それとsprintf文を使って、取り出した時と同じ桁数で出力させます。
  • 今度は、元の文字列に置き換えてみましょう。置き換えにはs///文を使います。
  • s/置き換え前の文字列/置き換え後の文字列/指定
  • s///は、”置き換え前の文字列” に正規表現を使う事ができます。置き換え後の文字列は固定です。(置き換え後の文字列にも正規表現を使う時は、tr///を使います。)
s/\d+/$num/;
  • は、変数_の中から(対象が指定されてないので_が使われます)、\d+つまり数字が連続している部分を探して、$numの値に置き換えます。
  • ここまでをサンプルプログラムにしました。
  • サンプル)文字列中の数字の部分を探して繰り上げる
    #!/usr/bin/perl
    $_="cyborg009";
    ketaup();
    printf("%s\n",$_);
    $_="kikaida-01";
    ketaup();
    printf("%s\n",$_);
    $_="ultra7";
    ketaup();
    printf("%s\n",$_);
    exit();
    sub ketaup() {
    /\d+/;
    my($keta)=length($&);
    my($format)="%0".$keta."d";
    my($num)=sprintf($format,$&+1);
    s/\d+/$num/;
    } 
  • 実行結果)
    cyborg010
    kikaida-02
    ultra8 
  • 解説
  • cyborg009という文字列をセットして、ketaup()関数を呼びます。ここでは、数字の部分を+1して元の文字列に置き換えます。引数もリターンコードもない関数ですが、すべてグローバル変数$_が暗黙に使われています。
  • 結果として、cyborg010という文字列が返ります。