(3)正規表現について
前ページまでで、文字列の置換や種類をチェックする方法を紹介しました。今回は簡単な操作でしたので、独自のメソッドを作成して対応するのもそれほど大変ではありませんでした。ブックマーク集などの小さなWebアプリケーションでしたら、このような対応でも十分間に合います。しかし、実際のWebアプリケーションでは、より複雑な入力チェックを行う場面が多いでしょう。例えば、入力された文字列がメールアドレスとして妥当であるかのチェックや、またはURLとして妥当であるか、などのチェックも必要になることがあります。HTMLタグの入力を禁止している個所でも、<FONT></FONT>などの害のなさそうなタグは有効にしたい場合があるかもしれません。そのような場合、それぞれをチェックするために新しいメソッドをそのたびに作成していたのでは大変です。Perlでのプログラミング経験をお持ちの方なら、正規表現を使って簡単に対応したいと思われるかもしれません。
しかしながら、JDK 1.3では正規表現が正式にサポートされていません。そのため、独自のメソッドを作るか、もしくはサードパーティが公開している正規表現ライブラリを使用する必要があります。次のバージョンであるJDK 1.4からは、正規表現が標準APIとしてサポートされるため、文字列処理がより簡単になることでしょう。
ここではJDK 1.3で正規表現を使うために、Jakarta OROを使用する方法と、JDK 1.4からサポートされる正規表現APIの使用方法について説明します。
正規表現とは
正規表現とは、文字列の一部を一般化することで、特定の条件を満たす文字列を表現するための表記方法です。
例えば「記号'.'は任意の1文字を表し、記号'+'は1回以上繰り返すことを意味する」というような決まり事により、「http://www.atmarkit.co.jp/」「http://www.sun.co.jp/」「http://www.yahoo.co.jp/」のそれぞれの文字列はすべて「http://www\..+\.co\.jp/」という正規表現で表すことができます。「“http://www.”で始まり、それに続く文字列は何でも構わないが、“.co.jp/”で終わる」というような、「文字列が満たすべき条件」を効率良く記述できる表現手法なのです。
この例で挙げた“.”や“+”のような特殊な記号を「メタ文字」と呼び、主に次のようなものがあります(メタ文字として使用される文字そのものを表すには“\”でエスケープします)。
. | 任意の1文字を表します |
---|---|
* | 直前の表現が0回以上繰り返すことを表します |
+ | 直前の表現が1回以上繰り返すことを表します |
? | 直前の表現が0回か1回出現することを表します |
{} | 直前の表現の繰り返し回数を表します |
[] | []内に存在する文字のうち1文字を表します |
上記以外にも、さまざまなメタ文字が存在します。これらを組み合わせることで、処理の対象となる文字列が満たすべき複雑な条件を、短い記述で表現することができます。
Jakarta OROの正規表現
Jakarta OROは、現在、Apache Software Foundationにてリリースされている、Jakartaプロジェクトの1つとして存在する正規表現ライブラリです。Perlで用いる正規表現の手法と大変似た方法で文字列操作が行えるため、Perl ユーザーには理解しやすいでしょう。現在は、実際の現場でも広く使われているようです。最新情報はJakarta OROのサイト(http://jakarta.apache.org/oro/)から得ることができます。執筆時現在、2.0.4が最新バージョンとなっています。インストール方法などは上記のサイトを参照してください。
前ページまでの紹介でMyUtilクラスに追加したHTMLEscapeとdigitAlphabetCheck メソッドをJakarta OROを用いて作成すると、次のようになります。
1: package atmarkit; 2: 3: import org.apache.oro.text.perl.*; 4: 5: public class MyUtilORO { 6: 7: static public String HTMLEscape(String input) { 8: Perl5Util util = new Perl5Util(); 9: input = util.substitute("s/&/&/g", input); 10: input = util.substitute("s/</</g", input); 11: input = util.substitute("s/>/>/g", input); 12: input = util.substitute("s/\"/"/g", input); 13: return input; 14: } 15: 16: static public boolean digitAlphabetCheck(String input) { 17: Perl5Util util = new Perl5Util(); 18: return !util.match("m/[^a-z0-9]/i", input); 19: } 20: }
Perlで見慣れた正規表現を使用できるのが分かると思います。Perl5Utilのインスタンスを生成し、それに対してsubstituteやmatchのメソッドを実行するだけですので、コードもシンプルになっています。しかしながら、Perl 5 に類似したインターフェイスで扱える半面、パフォーマンスはそれほど良くないといわれています。Jakarta OROには、同等の機能を提供しながら、より処理速度の速いorg.apache.oro.text.regexパッケージも準備されています。こちらは、コーディングが若干複雑になります。詳しくはJakarta OROサイトのドキュメントを参照してください。
JDK1.4 の正規表現
JDK 1.4は執筆時現在、ベータ2が最新のものとなっています。JDK 1.4からjava.util.regexパッケージが標準で含まれるようになり、標準APIの範囲でJavaでも正規表現が扱えるようになります。
先ほどJakarta OROを用いて作成したHTMLEscapeとdigitAlphabetCheckメソッドをJDK 1.4のjava.util.regexパッケージを用いて作成すると、次のようになります。
1: package atmarkit; 2: 3: import java.util.regex.*; 4: 5: public class MyUtilJDK14 { 6: 7: static public String substitute(String input, String ptn, String replacement) { 8: Pattern pattern = Pattern.compile(ptn); 9: Matcher matcher = pattern.matcher(input); 10: return matcher.replaceAll(replacement); 11: } 12: 13: static public String HTMLEscape(String input) { 14: input = substitute(input, "&", "&"); 15: input = substitute(input, "\\<", "<"); 16: input = substitute(input, "\\>", ">"); 17: input = substitute(input, "\"", """); 18: return input; 19: } 20: 21: static public boolean digitAlphabetCheck(String input) { 22: Pattern pattern = Pattern.compile("[^a-z0-9]", Pattern.CASE_INSENSITIVE); 23: Matcher matcher = pattern.matcher(input); 24: return !matcher.find(); 25: } 26: }
JDK 1.4のjava.util.regexパッケージを用いた場合、PatternとMatcherという2つのクラスのインスタンスを生成して、文字列の処理を行うことになります。上記のコードは、JDK 1.4 ベータ2で動作確認しています(<、>の記号は、それぞれ単語の始点、終点を意味するものとして認識されてしまうらしく、\でエスケープすることで意図した処理を行うことができました)。
詳しくはSun Microsystemsのサイト(http://java.sun.com/)の情報を参照してください。
今回の例は、簡単な文字列処理であったため、正規表現のありがたみはあまり感じられないかもしれません。しかし、例えばテキスト文字列の中からURLに該当する文字列を探し出し、そこにリンクを張るような処理を考えると、正規表現を用いずに実現するのは困難です。行うべき文字列処理が複雑であればあるほど、正規表現を用いる意味が出てくるといえます。また、Jakarta ORO、JDK 1.4のjava.util.regexパッケージともに、後方参照の機能があるので、パターンマッチした部分文字列を用いた処理が可能です。必要に応じて、正規表現ライブラリの導入を検討してください。
Copyright © ITmedia, Inc. All Rights Reserved.