JSPで正規表現

スクリプト言語ではじめに正規表現を触ると,Java正規表現がムドーか何かに見えてきます.ドラクエやった事無いけど,きっとムドーってこんな感じだと思う.
なんて手間がかかるんだろう,なんて回りくどいんだろう.Javaっ子は,PerlRuby正規表現を,見て見ぬ振りするんでしょうか.少なくともAgileで無いのは確か.今日はそんな素敵な正規表現を使ってみたいと思います.

java.util.regex......

Javaで最も標準的であろう,正規表現パッケージ,java.util.regex.詳しい情報は,Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle(日本語)にて.とりあえずコレを使って色々検証します.まぁ別の正規表現パッケージをしらないし,わざわざ入れるのも面倒くさいし.

兎に角マッチ

まずは簡単な例から始めます.
たとえば,あるユーザIDにマッチさせたいとします.そのユーザIDは半角英数字(アルファベットは小文字だけ)で構成されており,先頭はアルファベットで,最低でも4文字以上,最長で10文字である事が条件である,とします.
簡単のため,先ずはRubyで.

p = /^[a-z][a-z0-9]{3,9}$/

uid = []
uid.push "omochi11" # 普通
uid.push "Omochi" # 英大文字がある
uid.push "moc" # 3文字(短い)
uid.push "moch" # 4文字(ギリ)
uid.push "omochiumas" # 10文字(ギリ)
uid.push "omochioisis" # 11文字(長い)

uid.each{ |e|
  puts e if e =~ p
}

=>
$ ruby regex.rb 
omochi11
moch
omochiumas

ということで,正規表現

/^[a-z][a-z0-9]{3,9}$/

でよい,という事が分かります.勿論,0-9の部分を\dにしても問題ありません.それでは,同じような事をJSPで考えてみます.

uid = "omochi";
Pattern pattern = Pattern.compile("^[a-z][a-z0-9]{3,9}$");
Matcher matcher = pattern.matcher(uid);
if(matcher.matches()){
  out.println(uid);
}

簡単に説明をすると,文字列をPatternにコンパイルし,matcherでMatcherのインスタンスを生成し,そのインスタンスがmatches()というメソッドを呼び出しマッチの確認,booleanが返ってくる.
もちろん,こちらも0-9を置き換える事が出来る.ただし,\\dで.バックスラッシュ2回ってのが初め分からなくて,軽くハマりました.しかしながら,詳説正規表現に書いていた気がしないでもない.


しかし,これはまだ一つしかマッチの確認をしていないのだよね.もし複数個のマッチの確認をしようというのなら,たとえばこんな感じになるだろう.

// uidは配列,中に文字列が格納されていると仮定
Pattern pattern = Pattern.compile("^[a-z][a-z0-9]{3,9}$");
Matcher matcher; // 宣言だけ
for(int i ; i < uid.length() ; i++){
  matcher = pattern.matcher(uid[i]);
  if(matcher.matches()){
    out.println(uid[i]);
  }
}

なんだかとっても回りくどい感じがするけど,きっとこうしてクラスがPattern,Matcherとあることで,色々便利なんでしょうよ.スクリプト言語の文化に浸ってしまうと,結構抜けられないものだなぁ.

簡単なサニタイジング

JSPPHPCGIなどのウェブアプリケーションを使う以上,サニタイジングという技術は欠かす事が出来ません.
もちろんJSPにもあるよね〜とか思って探したんですが(友達にも手伝ってもらったけど),見つからなかった.そこで,正規表現を使って,使用禁止な文字があったら入力エラーとかでも吐かす事にします.


SQLのクエリとかも考慮すると,入力しちゃ不味い文字は

\<>&\"'(),;

ぐらいかしら.それじゃ早速JSPで.

Pattern p_sanitize = Pattern.compile("^[^\\\\<>&\"'(),;]*$"); 
Matcher m_canuse = p_sanitize.matcher(value);

if(!m_canuse.matches()){
  %>
	<p>入力に使用できない文字列が含まれています.</p>
	<form>
	<input type="button" value = "戻る" onClick = "javascript:history.back()">
	</form>
	<%
}

こんな感じ.\をマッチさせるために,なんか必死.とりあえずはこれでヤバい入力は避けられそうです.


結局何が言いたいのかと言うと,JSPなら簡単にスパゲッティ書く自信がある,ってこと.実際,大量生産してるし.
Servlet必須だわ.やりかたわかんないよ.