正規表現(基礎編2)

Perl初心者のためのPerlノートです!

HTML/ CSS/ CGI-Perl/ JavaScript/ JavaApplet/ AccessUp/ Internet/ EnglishLearn/ ちゃいちゃん天使/ 天使メッセージ/ 飯田ワールド/ 結城ワールド/ プロフィール/ WEB相談室/ WEBアンテナ/ WEBリーダー/ 燈明日記/ yahoo

◆ はじめに

本ページは、私がPerlを習得した時(いや習得中)のノートです。

ごく普通の言語(COBOL,C,Java,VB等)を知っている人が、Perlをやり始めるといろいろと悩むことがあります。

それは、

です。

本ページは、そのようなハードルを一つ一つクリアにしていけたらと思います。

そして、本ページが何かのお役に立てれば幸いです。では、ごゆっくりご覧ください。

尚、ご感想、ご意見、誤字、脱字、間違い等がありましたら遠慮なくPerlノート掲示板へご指摘ください。

◆ サイト最新情報

◆ コンテンツ

■ 正規表現(基礎編2)

引きつづき正規表現です。 置換処理、文字列の削除、最大マッチと最小マッチ、カッコを使った記憶、マッチ特殊変数について、 お勉強致しましょう。

まず、今回もサンプルプログラムのテストデータ、family2.html を用意します。

family2.htmlファイルの内容(HTML的には参考にしないてください。)
<HTML>
<!-- family2.html  -->
<TITLE>Koike family Home Page</TITLE>
<H3>koike family Home Page</H3>
Welcome to this page!<BR>
Chaichan is charming!<BR>
Hi Chaichan! < HI Macha!<BR>
&#169;1999-2000 ChaicanPAPA's world &#169;1999-2000 10倍ズバリ site<BR>
&#165;5000
</HTML>

上記をブラウザでみると以下の感じになります。

koike family Home Page

Welcome to this page!
Chaichan is charming!
Hi Chaichan! < HI Macha!
©1999-2000 ChaicanPAPA's world ©1999-2000 10倍ズバリ site
¥5000
1、置換処理

&#169;は著作権の意味ですが、数字ではわかりずらいので、&copyと書いても同じなので、置き換えてみましょう。

サンプル07 sample07.pl
  #!/usr/local/bin/perl
  while(<STDIN>){
        s/&#169;/&copy;/g;
        print;
  }

説明いたします。 まず、s/$#169;/&copy;/g;はfamily2.htmlの$#169をすべて&copy;に置き換えます。 gスイッチ がないと最初にマッチしたものの一つの置換になります。 では実行してみましょう。

% sample07.pl < family2.html
      :
&copy;1999-2000 ChaicanPAPA's world &copy;169;1999-2000 10倍ズバリ site<BR>
      :

上手くいきました。

つぎに、Hi と HI を Helloに置き換えてみましょう。

サンプル08 sample08.pl
  
  #!/usr/local/bin/perl
  while(<STDIN>){
        s/hi/Hello/ig;
        print;
  }

gスイッチと一緒にiスイッチを指定すると大文字小文字の関係なくマッチするようになります。 では実行してみましょう。

% sample08.pl < family2.html
      :
Hello Chaichan! < Hello Macha!<BR>
      :

上手くいきました。

2、文字列の削除

置換文字列を空にするとマッチした文字列は削除されます。

(サンプル09 sample09.pl)

family2.txtの以下の2行の&#xxx; を削除してみましょう。

&#169;1999-2000 ChaicanPAPA's world &#169;1999-2000 10倍ズバリ site<BR>

&#165;5000

  #!/usr/local/bin/perl
  while(<STDIN>){
        s/&#\d{1,3};//g;
        print;
  }

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

% sample09.pl < family2.html
       :
Chaichan is charming!<BR>
Hi Chaichan! < HI Macha!<BR>
1999-2000 ChaicanPAPA's world 1999-2000 10倍ズバリ site<BR>
5000
       :

上手くいきました。ちなみに \d{1,3} は 数字で1桁〜3桁の繰り返しです。

3、最大マッチと最小マッチ

つぎに、family2.htmlからタグを削除してみましょう。

タグは < ではじまり、 > で終わる文字列です。 「.」は任意の一文字で「*」は0回以上の繰り返しです。 ですので、以下のようなプログラムになります。

サンプル10 sample10.pl
  #!/usr/local/bin/perl
  while(<STDIN>){
        s/<.*>//g;
        print;
  }

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

% sample10.pl < family2.html
Welcome to this page!
Chaichan is charming!
Hi Chaichan! < HI Macha!
c1999-2000 ChaicanPAPA's world c1999-2000 10倍ズバリ site
\5000 

あれれ、<TITLE>Koike family Home Page</TITLE>と<H3>koike family Home Page</H3>が まるまる行毎、削除されてしまいました。 これは、<TITLE>の < から</TITLE>の > まで解釈されたためです。

実は、perlでは、パターンマッチがもっとも長い文字列とマッチする最大マッチなのです。 ですから、行毎削除されてしまいました。 では、<TITLE>、</TITLE>、<H3>や</H3>を削除するにはどうしたらいいでしょう? それは最小マッチの ? を利用します。

サンプル11 sample11.pl
  #!/usr/local/bin/perl
  while(<STDIN>){
        s/<.*?>//g;
        print;
  }

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

% sample11.pl < family2.html
Koike family Home Page
koike family Home Page
Welcome to this page!
Chaichan is charming!
Hi Chaichan! < HI Macha!
c1999-2000 ChaicanPAPA's world c1999-2000 10倍ズバリ site
\5000 

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

4、カッコを使った記憶

まず、今回もサンプルプログラムのテストデータ、family3.txt を用意します。

macha koike
sayuri koike chaichan

このデータは「名前スペース苗字」の順番になっています。 これを「苗字カンマ名前」に替えてみましょう。

(サンプル12 sample12.pl)
  #!/usr/local/bin/perl
  while(<STDIN>){
        s/(\S+) (\S+)/$2,$1/;
        print;
  }
% sample11.pl < family3.txt
koike,macha
koike,sayuri chaichan

上手くいきました。ポイントは s/(\S+) (\S+)/$2,$1/; だけです。 説明いたします。

\S はスペース以外の一文字以外です。これが、スペースをはさんで2つになっています。 つまり、パターン全体が「名前スペース苗字」にマッチします。

(〜)は〜の記憶を意味し、先出た順に、記憶したものが $1,$2,$3・・・に格納されます。 今回の場合は $1 に名前、$2 に苗字が格納されます。そこで、 $2,$1に置き換えます。

また、$1,$2,$3・・・は置換文字列だけでなく、パターンマッチのあとで好きなように使えます。

サンプル13 sample13.pl
  #!/usr/local/bin/perl
  $n = 0;
  while(<STDIN>){
        /(\S+) (\S+)/;
        ++$n;
        print "*** $n ***\n";
        print "苗字: $2\n";
        print "名前: $1\n";
        print "\n";
  }
 
% sample13.pl < family3.txt
*** 1 ***
苗字:koike
名前:macha

*** 2 ***
苗字:koike
名前:sayuri
5、マッチ特殊変数

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

サンプル14 sample14.pl
  #!/usr/local/bin/perl
  $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";
  }
% 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)で削除します。

正規表現はこのぐらいにします。 わかってくると結構楽しいですね。もっと早くマスターすればよかった...。 ちなみに、基礎編1、2だけで、応用編はありません。 みなさん、各自、正規表現で遊んでみてください。それが、応用編の代わりです。ではまた...。

◆ おすすめ Perl本

■ 続・初めてのPerl 改訂版

『初めてのPerl』の次ぎに読むと吉です。

結構いいですが・・・、初心者にはちょっと難しいかもです。

■ 結城浩のPerlクイズ

この本には、ちゃいちゃんパパの小話しが載っています(謎)。

ある程度、Perlを理解している人には、たまらない内容になっています。さすが結城先生だな!

結城浩のPerlクイズ

■ 新版Perl言語プログラミングレッスン入門編

実は、私はまだ読んでいませんが、結城先生の本なので良くないはずがありません。

新版Perl言語プログラミングレッスン入門編

■ CGI&Perlポケットリファレンス (Pocket reference)

この本は、非常に役に立ちます。ちょっと調べるのに最適です。サンプルも説明も的を射ています。

CGI&Perlポケットリファレンス (Pocket reference)

■ Perlベストプラクティス

一読の価値有りだと思います。

Perlベストプラクティス

■ プログラミングPerl〈VOLUME1〉

ご存知、Perl本の聖書、ラクダ本(上)です。

■ プログラミングPerl〈VOLUME2〉

ご存知、Perl本の聖書、ラクダ本(下)です。

◆ おわりに

最後に、本ページが、何かのお役に立てれば幸いです。

尚、ご感想、ご意見、誤字、脱字、間違い等がありましたら遠慮なくPerlノート掲示板へご指摘ください。

HTML/ CSS/ CGI-Perl/ JavaScript/ JavaApplet/ AccessUp/ Internet/ EnglishLearn/ ちゃいちゃん天使/ 天使メッセージ/ 飯田ワールド/ 結城ワールド/ プロフィール/ WEB相談室/ WEBアンテナ/ WEBリーダー/ 燈明日記/ yahoo

人のよいところをどんどん見つけよう