「初めてのPerl」 7章 (正規表現の基本)

男子サッカー日本代表は、「ジーコジャパン」、「オシムジャパン」、「反町ジャパン」って感じで「監督名ジャパン」と呼ばれるのに、女子サッカーは「なでしこジャパン」と呼ばれていることにすごく違和感を感じているbonlifeです。Perlの勉強、それなりに順調です。次々と進めてRubyの勉強に着手したいところ。(という欲張りはあまり良くないのでしょうか。)さて、7章では正規表現の基本について説明されています。Perlでは「パターン」と言うらしいです。スラッシュ(/)で囲んでパターンを指定し、if文などで真偽を判断します。メタキャラクタの説明も少し。ドット(.)は改行文字を除いたあらゆる文字1個にマッチします。量指定子についての説明もありました。アスタリスク(*)は直前のもの0回以上にマッチし、プラス記号(+)は直前のものの1回以上にマッチします。後は、カッコ()でグルーピングしたり、縦棒(|)を使ってどちらかにマッチさせる、などなど。秀丸の検索、置換の際にも正規表現は使うので、このあたりはだいたい理解しているつもりです。ということで7章の演習問題のnot模範解答です。
ex7-1.pl

  • fredを含むようなすべての文字列にマッチするパターンを作成し、テスト
#! perl -w
use strict;
print "Please input some words : \n";
while (<>) {
	chomp;
	if (/fred/) {
		print "Matched : | $`<$&>$' |\n";
	} else {
		print "No match.\n";
	}
}

出力結果は以下の通り。

ex7-1.pl
Please input some words :
fred
Matched : | <fred> |
Fred
No match.
frederick
Matched : | <fred>erick |
Alfred
Matched : | Al<fred> |
^Z

解答例を見て気づいたことは特になし。同じ。
ex7-2.pl

  • 少なくとも1個のaの後ろに任意個のbが続くような文字列にマッチするパターンを作成し、テスト
#! perl -w
use strict;
print "Please input some words : \n";
while (<>) {
	chomp;
	if (/a+b*/) {
		print "Matched : | $`<$&>$' |\n";
	} else {
		print "No match.\n";
	}
}

出力結果は以下の通り。

ex7-2.pl
Please input some words :
barney
Matched : | b<a>rney |
fred
No match.
abba
Matched : | <abb>a |
dinosaur
Matched : | dinos<a>ur |
^Z

解答例を見て気づいたことは特になし。同じ。
ex7-3.pl

  • 任意個の逆スラッシュの後ろに任意個のアスタリスクが続くような文字列にマッチするパターンを作成し、テスト
#! perl -w
use strict;
print "Please input some words : \n";
while (<>) {
	chomp;
	if (/\\*\**/) {
		print "Matched : | $`<$&>$' |\n";
	} else {
		print "No match.\n";
	}
}

出力結果は以下の通り。

ex7-3.pl
Please input some words :
a
Matched : | <>a |
a
C:\test\perl>ex7-3.pl
Please input some words :
\\**
Matched : | <\\**> |
fred
Matched : | <>fred |
barney \\\***
Matched : | <>barney \\\*** |
*wilma\
Matched : | <*>wilma\ |
^Z

解答例を見て気づいたことは特になし。同じ。
ex7-4.pl

  • wilmaを含むようなすべての入力行を表示するプログラムを書く
  • 大文字で始まるWilmaにもマッチさせる
#! perl -w
use strict;
while (<>) {
	chomp;
	if (/(^|\s)[wW]ilma([^\w]|$)/) {
		print "$_\n";
	} else {
	}
}

引数として渡すサンプルテキスト

  • wilma.txt
Wilma always sleeps.
Am I Wilman?
No, I'm Wilma.
WILMA is so big!
Oh, small wilma...

出力結果は以下の通り。

ex7-4.pl wilma.txt
Wilma always sleeps.
No, I'm Wilma.
Oh, small wilma...

解答例を見て気付いたことは以下の通り。

  • ここではあまり難しく考える必要はなかったようです (解答例では/(w|W)ilma/)
  • elseは不要

ex7-5.pl

  • wilmaとfredの両方が含まれている行を表示するプログラムを書く
#! perl -w
use strict;
while (<>) {
	chomp;
	if (/(^|\s)[wW]ilma([^\w]|\s).*[fF]red([^\w]|$)|(^|\s)[fF]red([^\w]|\s).*[wW]ilma([^\w]|$)/) {
		print "$_\n";
	} else {
	}
}

引数として渡すサンプルテキスト

  • wilma_and_fred.txt
wilma and fred
WILMA AND FRED
Wilma and Fred
wilmafred
wilma! and fred!
awilma afred

出力結果は以下の通り。

ex7-5.pl wilma_and_fred.txt
wilma and fred
Wilma and Fred
wilma! fred!

解答例を見て気付いたことは以下の通り。

  • if文のネストで2回判断する方法でも対応可能
  • elseは不要

このくらいのレベルであれば特に迷うこともなく書くことができますね。正規表現は極めようとするとすごく大変そうですが、ちょっと使う分には結構イージーです。とか言ってますが、私の場合、見慣れるまでに結構時間がかかりましたが(苦笑)。