|
正規表現
省略できるものはとことん省略する
Perlという言語は省略できるものは省略してしまおうという気質が強い言語です。
これが良くもあり悪くもある部分かもしれません。
省略ができるのでプログラムのソースは美しく(独断と偏見ですが)なるのですが、可読性
が低くなり、作った本人かよほどよく分かる人でないとなんのことなのか分かりにくいプ
ログラムになることがあります。
でも、これをクリアすると気持ち良くなるのでがんばりましょう。私もがんばります。
正規表現とはパターンを表す式
正規表現とは、文字列をパターン化して表現することです。
Perlはこの部分が非常に特化しています。
正規表現の構文
パターンマッチ |
$x =~ /パターン/オプション |
左辺の文字列が右辺のパターンと一致するかどうかをチェックします。
マッチすれば 1 を、マッチしなければ "" を返します。
マッチとは検索機能のことです。
|
パターンパッチの否定形 |
$x !~ /パターン/オプション |
マッチすれば ""、しなければ 1 を返します。 |
置き換え |
$x =~ s/パターン/置き換える文字/オプション |
$x の中で、パターンに一致するものを置き換える文字に置き換えます。 |
例、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$x = 'CG小説漫画アニメゲーム攻略やおいドリーム';
print "A.".$x=~/鬼畜/."<br>";
print "B.".$x=~/アニメ/."<br>";
↓
A.
B.1
|
1行目は鬼畜が見つからなかったので""に、2行目ではアニメが見つかったので 1 にな
りました。
正規表現はこのままで使うことはあまりなく、if文などとセットで使われることが多いで
す。
例、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$x = 'CG小説漫画アニメゲーム攻略やおいドリーム';
if ($x=~/鬼畜/) {print "鬼畜があります。";}
else {print "鬼畜はありません。";}
↓
鬼畜はありません。
|
$_
特殊変数 $_ を使うと省略できます。
例、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = 'CG小説漫画アニメゲーム攻略やおいドリーム';
if (/鬼畜/) {print "鬼畜があります。";}
else {print "鬼畜はありません。";}
↓
鬼畜はありません。
|
m
スラッシュで区切りを立てていますが、前に m をつけるとスラッシュの変わりに任意の
記号を使うことが出来ます。
オプション
おしりにオプションをつけることにより色々な機能を追加できます。
オプション | 意味 |
g | 繰り返しマッチする |
i | 大文字と小文字の区別をしない |
o | 変数展開(コンパイル)を1度だけ行う |
m | 文字列を複数行として扱う |
s | 文字列を単一行として扱う |
x | 空白やコメントを許可します |
e | 文字列を式とみなす |
oオプションは1度の実行で使い回しをするもののうち、その実行内で中の変数がいつ
も同じならつけておくと処理が早くなります。ループ文の中などにお薦め。
oオプションの間違った使い方。
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$x = 'アルビノ、オッドアイ、クール、サドマゾ、';
print "$x<BR>";
&seiki("オッドアイ");
&seiki("人見知り");
sub seiki {
my $y = shift;
if ($x=~/$y/o) {print "$yがあります。<BR>";}
else {print "$yはありません。<BR>";}
}
↓
アルビノ、オッドアイ、クール、サドマゾ、
オッドアイがあります。
人見知りがあります。
(処理はちょっぴり早くなるoオプションなんだけど、この場合はおかしな具合になります。)
|
m と g で挟むと正規表現でマッチした結果を配列に代入してくれます。
ex.4ケタの数字にマッチしたものを@hogeに代入。
my @hoge=$hage=~m/\d{4}/g;
|
メタ文字
以下の記号はそれ自体に特殊な意味をもっていて、そのままではマッチできないので前に
\ をつけます。
\ ^ . $ * ? | ( ) [ ] { }
メタ文字の意味
メタ文字 | 意味 |
\ | 直後の文字をエスケープ |
^ | 先頭にマッチ |
.(ドット) | 改行を除く任意の1文字 |
$ | 末尾にマッチ |
| | どれかにマッチ |
() | グループ化 |
[] | 指定内の任意表現 |
\ の例(特殊文字の前には\) |
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$price = 'この同人誌は $10です';
if ($price =~ /\$/) {print "含まれています";}
else {print "含まれていません";}
↓
含まれています
|
^ (キャレット)の例(先頭の1文字)) |
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = 'yaoi';
if (/^y/) {print "マッチします";}
else {print "マッチしません";}
↓
マッチします
|
. (ドット)の例(任意の1文字) |
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = '私は眼鏡が好きです。';
if (/私は....が好きです。/) {print "いけてます";}
else {print "いけてません";}
↓
いけてます
(眼鏡の部分は全角なのでドット4つ分)
複数行の文字列で .(ドット) を「改行を含む任意の1文字」っぽくしたい場合は後ろにオプションの s をつけます。
ex.<!-- start --> と <!-- end --> で挟まれたもの(改行含)を
( ゚Д゚)y―┛~~に置換え
$hoge~=s/<!-- start -->.*<!-- end -->/( ゚Д゚)y―┛~~/s;
|
$ の例(最後の1文字) |
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = '化粧品に5000円はつらいが、ゲームソフトなら可';
if (/可$/) {print "親友になってください";}
else {print "住む世界がちがいます";}
↓
親友になってください
|
| (パイプ)の例(or) |
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = 'ハーレムアニメはにゃ〜ん破壊力抜群あんたヴァカァ?';
if (/PC|ゲーム|ヴァカ/) {print "マッチしてしまいました";}
else {print "マッチしません";}
↓
マッチしてしまいました
|
() (バーレン)の例(グループ化) |
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = '(´∀`)123-4567';
if (/^(´∀`)(\d{3})-(\d{4})/) {print "郵便番号とかかも<BR>";}
else {print "( ´_ゝ`)<BR>";}
print "$_<BR>";
print "$1<BR>";
print "$2<BR>";
↓
郵便番号とかかも
(´∀`)123-4567
123
4567
- ^ は先頭ですよ、という意味。
- \d{3}は3桁の数字を表します。
- 上の正規表現は (´∀`)が先頭で、その後、数字3つ -(ハイフン) 数字4つ の形式に当てはまるもの、という意味です。
- このとき、\d{3}を囲むカッコは無くても良いのでが、つけておくとあとで変数として利用できます。
- 2-4行目の表示でも分かるように、前から順番に $1、$2 という特殊変数に代入されているのが分かります。
|
[](ブラケットの例) |
[]ではさまれたもののうちどれかという意味。
先頭に^が有れば逆にそれ以外という意味。
例、
[a-z] アルファベット小文字の aからz のいずれか1文字にマッチする。
[a-zA-Z0-9] 英数字文字
[^a-zA-Z0-9] 英数字以外
|
量の指定
記号 | 意味 |
* | 0個以上にマッチ |
+ | 1個以上にマッチ |
? | 0または1個にマッチ |
{n} | n個にマッチ |
{n,} | n個以上にマッチ |
{n,m} | n個以上m個以下にマッチ |
例、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = 'Loli:1 Ota:2 Poo:3';
if (/(.+[0-9])/) { print "マッチしてしまいましたか"; }
else { print "マッチしません"; }
↓
マッチしてしまいましたか
(数字の前に1個以上連続しているなにか、という形式の文字列がある)
|
最短マッチ
上の例では Loli:1 Ota:2 Poo:3 という文字がマッチしましたが、細かいことを言うと
Loli:1 も Ota:2 も Poo:3 もそれぞれが該当します。
いったいどれに反応したのかというと、上の場合では Loli:1 Ota:2 Poo:3 全体に反応しまし
た。
で、左から数えて最短距離まででチェックしたいときには後ろに ? をつけます。
こんな感じ。
記号 | 意味(左から数えて最短距離までチェックする) |
*? | 0個以上にマッチ |
+? | 1個以上にマッチ |
?? | 0または1個にマッチ |
{n}? | n個にマッチ |
{n,}? | n個以上にマッチ |
{n,m}? | n個以上m個以下にマッチ |
例、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = 'Loli:1 Ota:3 Poo:2';
if (/(.+[0-9])/) {print $1;} print "<br>";
if (/(.+?[0-9])/){print $1;}
↓
Loli:1 Ota:3 Poo:2
Loli:1
|
他、略語みたいなもの
略語 | 意味 |
\w | 英字、数字、アンダースコア。[a-zA-Z0-9_] に同じ。 |
\W | 英字、数字、アンダースコア以外の文字。[^a-zA-Z0-9_] に同じ。 |
\d | 数字。[0-9] に同じ。 |
\D | 数字以外の文字。[^0-9] に同じ。 |
\t | タブ |
\r | リターン(復帰文字) |
\n | 改行 |
\f | ラインフィード(改ページ) |
\s | スペース。[ \r\t\n\f] に同じ。 |
\S | スペース以外の文字。[^ \r\t\n\f] に同じ。 |
\a | アラーム(ベル) |
\b | バックスペース |
\e | エスケープ |
\0 + 数字 | 8進法で表すASCII文字。( ex. \033, \040 など ) |
\x + 英数字 | 16進法で表すASCII文字。( ex. \x1b, \x00 など ) |
\c[ | コントロール文字 |
\l | 次の1文字を小文字にする |
\u | 次の1文字を大文字にする |
\L | \Eまでの文字列を小文字にする |
\U | \Eまでの文字列を大文字にする |
\E | 変更の終わり |
\Q | \Eまでの文字列で正規表現のメタ文字を文字にみなす |
\b | 単語の境界にマッチする |
\B | 単語の境界以外にマッチする |
\A | 文字列の最初にマッチする。メタ文字 ^ に同じ。 |
\Z | 文字列の最後にマッチする。メタ文字 $ に同じ。 |
$ + 数 | グループ化したパターンを後で参照する。( ex. $1, $2, $3, ... ) |
\ + 数字 | 上記に同じ。( ex. \1, \2, \3, ... ) |
$& | マッチした文字列全体 |
$` | マッチした文字列の前にあるすべての文字列 |
$' | マッチした文字列の後にあるすべての文字列 |
ついで
正規表現とは関係ないですが「置き換え」と似てるので。
tr/変換する文字/変換後の文字/ |
y/変換する文字/変換後の文字/ |
tr も y も同じです。これは文字を置き換えて、なおかつその文字数を返します。
オプションの g は要りません。
例、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$_ = 'otaku maniac nerd geek techie';
print tr/a-z/A-Z/; print "<br>";
print;
↓
25
OTAKU MANIAC NERD GEEK TECHIE
|
そのオプション。
オプション | 意味 |
c | 変換対象以外の文字を変換する。 |
d | 対応する変換後の文字が無ければその文字を削除する。 |
s | 変換の結果、同じ文字が続く場合は1文字にまとめる。 |
配列←→文字列
正規表現を利用する関数として split関数があります。
例えば、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
$x = 'otaku:maniac:nerd:geek:techie';
@x = split /:/,$x;
print $x[0]."<br>";
print $x[1]."<br>";
print $x[2]."<br>";
↓
otaku
maniac
nerd
|
$x 内の文字を // ではさんだものを区切り文字として、@x にセットしました。
文字列に $_ を指定した場合は @x=split/:/;でもよいです。
@x = split /:/,$x,2; というように後ろに数字を入れるとその数までしか分割しません。
↓
otaku
maniac:nerd:geek:techie
反対に、join という関数を使うと、配列を文字列に変換します。
例、
#!c:/perl/bin/perl
print "Content-type: text/html; Charset=Shift_JIS\n\n";
@x = ("otaku","maniac","nerd","geek","techie");
$x = join ",", @x;
print $x;
↓
otaku,maniac,nerd,geek,techie
|
join の方も正規表現とは関係ありませんが、split と対ということで。
|
|
|
|