perlでCGIを書く(3)
正規表現
文字列から、ある特定のパターンを検出して置換や削除などの処理を施すことができます。正規表現とは、定められた記号を利用してその
文字列パターンを表現するものです。
検出に必要な文字列パターンを指定するのに、文字クラスと呼ばれる表現があります。
文字クラスや正規表現的に意味を持つ記号($や*など)そのものにマッチさせたい場合はバックスラッシュでエスケープするか、
文字クラスや繰り返しの記号は、単に「左の記号は右の意味を持つ」というだけのことであり、右の意味を表現する為に対応する左の記号を全て使わねばならない、という意味ではありません。
perlは、同じ結果を得るために幾通りもの書き方がある言語ですから、いささか乱暴な表現ですが、[]と.と*だけしか覚えていなくとも実用に耐えるプログラムは書けるものです。
「<と>で挟まれた、短い方の文字列」にマッチングさせるには、繰り返し指定の記号(*,+など)に ? を付加します。
a) (?:文字列)
$1,$2,...といった後方参照を作りません。
b) (?=文字列) 末尾方向認識アサーション。/文字列1(?=文字列2)/xの指定で、?=以下の文字列2が続く文字列1にマッチします。
c) (?!文字列) 否定の末尾方向認識アサーション。上記(b)の例では、後ろにScriptという文字列を従えないJavaにマッチします。
d) (?<=文字列) 先頭方向認識アサーション。/($<=文字列2)文字列1/xの書式で、先頭に文字列2を従えた文字列1にマッチします。
e) (?<!文字列) 否定の先頭方向認識アサーション。(b)〜(e)の4つのパターンでは、特殊変数$&に格納されるのはすべて(文字列1)のみです。
f) (?(条件)真のときの文字列|偽のときの文字列)
()内に書かれた条件(整数)の真偽によってマッチさせる文字列が変わるというシロモノ。
例えば性別が女性なら1というフラグを設定しておき、()内の条件が真なら/female/にマッチさせ、偽なら/male/にマッチさせるなどの用法があります。
条件が偽の時の文字列は省略することができます。
記述例;
- /bonmee/ ・・・ bonmeeという文字列にマッチ
- /^bonmee/ ・・・ bonmeeで始まる文字列にマッチ
- /bonmee$/ ・・・ bonmeeで終わる文字列にマッチ
- /(bon|mee)/ ・・・ bonまたはmeeという文字列にマッチ
検出に必要な文字列パターンを指定するのに、文字クラスと呼ばれる表現があります。
文字クラス;
指定された条件に合う1文字にマッチします。大文字と小文字は区別されます。- [abc] → aかbかcのどれか
- [a-z] → 任意の小文字
- [^a-z] → 小文字以外
- \d → 数字
- \D → 数字以外
- \w → 英数字
- \W → 英数字以外
- \s → 空白文字
- \S → 空白文字以外
- . → 任意の1文字
文字クラスや正規表現的に意味を持つ記号($や*など)そのものにマッチさせたい場合はバックスラッシュでエスケープするか、
例)/http\:\/\//もしくはm|文字列|を使用します。
例)m|///| → スラッシュ3つにマッチ
繰り返しの指定;
以下の記号を使い、文字または文字クラスの繰り返しとマッチします。- * → 0回以上の繰り返し
- + → 1回以上の繰り返し
- ? → 0回、または1回
- {3} → 3回
- {3,} → 3回以上
- {3,5} → 3回以上、5回以下
文字クラスや繰り返しの記号は、単に「左の記号は右の意味を持つ」というだけのことであり、右の意味を表現する為に対応する左の記号を全て使わねばならない、という意味ではありません。
perlは、同じ結果を得るために幾通りもの書き方がある言語ですから、いささか乱暴な表現ですが、[]と.と*だけしか覚えていなくとも実用に耐えるプログラムは書けるものです。
最長マッチと最短マッチ
perlの正規表現では、複数の可能性が考えられる場合は長い方を取る、という性質があります。
$_ = "<html>Match</html>"; @_ = /<.*>/;タグの中身(html, /html)だけを抽出したいと思って実行すると、@_には$_がすべて代入されてしまいます。左端の<と右端の>に挟まれた任意の文字列、と解釈されるのが理由です。
「<と>で挟まれた、短い方の文字列」にマッチングさせるには、繰り返し指定の記号(*,+など)に ? を付加します。
$_ = "<html>Match</html>"; @_ = /<.*?>/;
正規表現の拡張構文
perl5でサポートされる拡張構文。()内が?で始まり、x修飾子を付加します。a) (?:文字列)
$1,$2,...といった後方参照を作りません。
b) (?=文字列) 末尾方向認識アサーション。/文字列1(?=文字列2)/xの指定で、?=以下の文字列2が続く文字列1にマッチします。
例)/Java(?=Script)/x後ろにScriptと続くJavaにのみマッチします。$&に格納されるのはJavaのみです(Scriptは格納されません)。
c) (?!文字列) 否定の末尾方向認識アサーション。上記(b)の例では、後ろにScriptという文字列を従えないJavaにマッチします。
d) (?<=文字列) 先頭方向認識アサーション。/($<=文字列2)文字列1/xの書式で、先頭に文字列2を従えた文字列1にマッチします。
e) (?<!文字列) 否定の先頭方向認識アサーション。(b)〜(e)の4つのパターンでは、特殊変数$&に格納されるのはすべて(文字列1)のみです。
f) (?(条件)真のときの文字列|偽のときの文字列)
()内に書かれた条件(整数)の真偽によってマッチさせる文字列が変わるというシロモノ。
例えば性別が女性なら1というフラグを設定しておき、()内の条件が真なら/female/にマッチさせ、偽なら/male/にマッチさせるなどの用法があります。
条件が偽の時の文字列は省略することができます。
置換演算子
文字列aaaをbbbに置換する演算子を指します。
書式は s/(置換前の文字列)/(置換後の文字列)/ です。
置換演算子は、最初のひとつがマッチした時点で終了してしまう性質がありますので、文章中の全ての該当文字を置換したい場合はグローバルスイッチ(g)を付加します。
マッチさせる文字列には変数も使用できます。
上記では、スペースで区切られた文字列(Takuya Kimuraなど)にマッチさせ、スペースの左側が$1に、右側が$2に入ります。
$2と$1の順番を入れ換えることで、"Kimura Takuya"という形の表示ができます。
連続して置換することもできます。
大小文字の区別を無視するにはiスイッチを付加します。
その他;
s/// では無理な1文字単位の置換には tr/// を使用します。
書式は s/(置換前の文字列)/(置換後の文字列)/ です。
置換演算子は、最初のひとつがマッチした時点で終了してしまう性質がありますので、文章中の全ての該当文字を置換したい場合はグローバルスイッチ(g)を付加します。
while(<FILE>) {
s/Jan/Feb/g;
print;
}
これで、文章中の全ての"Jan"という文字列が"Feb"に置き換えられて表示されます。マッチさせる文字列には変数も使用できます。
$a = "Jan";
$b = "Feb";
while(<FILE>) {
s/$a/$b/g;
print;
}
マッチした文字列を変数に記憶させることもできます。
while(<FILE>) {
s/(\S+) (\S+)/($2) ($1)/g;
print;
}
マッチさせる文字を()で囲むと、マッチした順番に$1,$2...と変数に代入されます。上記では、スペースで区切られた文字列(Takuya Kimuraなど)にマッチさせ、スペースの左側が$1に、右側が$2に入ります。
$2と$1の順番を入れ換えることで、"Kimura Takuya"という形の表示ができます。
連続して置換することもできます。
$file = "http://hoge.com/fuga.dat"; $file =~ s/http\:\///g; $file =~ s/\/(.*)\///g; $file =~ s/\///g; print $file;最初にhttp:/が、次にhoge.comが、最後に/が削除(無に置換)されて、fuga.datだけが残ります。
大小文字の区別を無視するにはiスイッチを付加します。
s/<br>+$/\n/ig;ignore caseの頭文字の"i"だそうです。
その他;
- $` → マッチする前の文字列
- $& → マッチした文字列
- $' → マッチした後の文字列
- $+ → 最後にマッチした正規表現内の、最後の()内の文字列
s/// では無理な1文字単位の置換には tr/// を使用します。
tr/A-Z/a-z/;実行すると、全ての大文字が一気に小文字に置き換わります。
[ CGI Top ]
[ BACK ]
[ Reference Top ]
[ NEXT ]
[ HOME ]