ActionScript 3.0で始めるオブジェクト指向スクリプティング

第28回 正規表現で文字列を扱う

この記事を読むのに必要な時間:およそ 3 分

今回は,RegExpクラスについて学ぶ。このクラスが扱うのは,文字列のパターンだ。そのパターンの表現は多彩で,奥が深い。本稿は,いわばその入り口を紹介する。

RegExpクラスで正規表現を使う

RegExpクラスは,「正規表現」(Regular Expression)と呼ばれ,文字列のパターンを扱う。RegExpインスタンスでパターンを記述すると,文字列を調べたり,Stringクラスのメソッドに引数として渡すことにより文字列を操作できる。

RegExpクラスのコンストラクタには,第1引数としてパターンの指定を文字列で渡す。そして,生成されたRegExpインスタンスつまり正規表現は,まずRegExpクラスのメソッドで用いられる。

var 正規表現:RegExp = new RegExp(パターン)

RegExp.test()メソッドは,指定した文字列に正規表現のパターンに当てはまる文字列が含まれるかどうかを調べ,あればtrueなければfalseが返される。たとえば,文字列"Flashファイル(AS 3.0)"の中に,"AS"という文字列のパターンが存在するかどうかは,このパターンの文字列をRegExpコンストラクタに引数として渡し,RegExp.test()メソッドでつぎのように確かめればよい。[出力]パネルには,その存在を示すtrueが表示される。

var my_str:String = "Flashファイル(AS 3.0)";
var myPattern:RegExp = new RegExp("AS");
var bResult:Boolean = myPattern.test(my_str);
trace(bResult);   // 出力: true

RegExpインスタンスは,パターンを/(スラッシュ)で括って,リテラルで記述することもできる(「リテラル」については,第27回「XMLデータを扱う「XMLデータから必要な値を取出す」参照)。このときパターンの文字列にはクォーテーション"をつけないので注意しようスクリプト1参照)。

var 正規表現:RegExp = /パターン/

つぎのスクリプト1は,文字列が納められた配列(languages_array)からforループでエレメントを順に取出し,"Script"という文字列のパターンが含まれるエレメントのみを別の新たな配列(result_array)に加えたうえで[出力]する図1)。

スクリプト1 文字列の配列から正規表現のパターンに当てはまるエレメントを別の配列に取出す

// フレームアクション
var languages_array:Array = ["AS", "ActionScript", "JavaScript", "Java"];
var myPattern:RegExp = /Script/;
var result_array:Array = new Array();
var nLength:uint = languages_array.length;
for (var i:uint = 0; i < nLength; i++) {
  var language_str:String = languages_array[i];
  if (myPattern.test(language_str)) {
    result_array.push(language_str);
  }
}
trace(result_array);   // 出力: ActionScript,JavaScript

図1 正規表現のパターンに当てはまる文字列エレメントの配列が[出力]される

図1 正規表現のパターンに当てはまる文字列エレメントの配列が[出力]される

Stringクラスで正規表現を使う

Stringクラスのメソッドには,正規表現を引数として指定できるものがある。たとえば,String.replace()は,検索・置換のメソッドだ。第1引数にRegExpインスタンスを渡すと,そのパターンに当てはまる文字列を第2引数の文字列と置換える。

var 結果文字列:String = 対象文字列.replace(パターン, 置換文字列)

以下のスクリプトは,改行として復帰文字"\r"が用いられた文字列に対して,String.replace()メソッドを呼出し,"\r"を"<br>に置換える。String.replace()メソッドの第1引数には,RegExpインスタンス/\r/をパターンとして渡した。

var my_str:String = "Flash\rDreamweaver\rPhotoshop\rIllustrator";
var myPattern:RegExp = /\r/;
var result_str:String = my_str.replace(myPattern, "<br>");
trace(result_str);

このスクリプトのように単純に文字列だけを指定したRegExpインスタンスは,パターンに当てはまる最初の文字列を示す正規表現になる※1)。したがって,String.replace()メソッドの置換結果も,最初の改行("\r")のみが文字列"<br>"に変わり,あとの改行はそのまま残ってしまった図2)。

図2 パターンに複数当てはまっても置換えられるのは最初の文字列のみ

図2 パターンに複数当てはまっても置換えられるのは最初の文字列のみ

パターンと一致する文字列すべてを指定したいときには,正規表現に以下のようにg(global)フラグを添える。すると,今度はすべての改行("\r")が,正しく文字列"<br>"に変わる。[出力]はつぎのとおりだ図3)。

Flash<br>Dreamweaver<br>Photoshop<br>Illustrator
var my_str:String = "Flash\rDreamweaver\rPhotoshop\rIllustrator";
var myPattern:RegExp = /\r/g;
var result_str:String = my_str.replace(myPattern, "<br>");
trace(result_str);

図3 パターンに当てはまる文字列すべてが置換えられる

図3 パターンに当てはまる文字列すべてが置換えられる

複数のパターンのいずれかひとつを対象とする指定は,選択制御文字|を用いる。もちろん,パターンの数はいくつでも構わない。

var 正規表現:RegExp = /パターンA|パターンB/

たとえば,テキストファイルの改行コードは,プラットフォームによって異なる。Windowsは復帰文字+改行文字("\r\n"),Macintoshが復帰文字("\r"),UNIXやLinuxは改行文字("\n")だ。これらいずれのファイルの改行コードであっても同じパターンとして扱いたい場合には,つぎのような正規表現を指定すればよい。

var myPattern:RegExp = /\r\n|\r|\n/

改行コードを意識して解析しなければならない例としては,CSV(カンマ区切り)データの扱いが考えられる。CSVは,1件のデータ(レコード)を改行で区切り,その中の項目(フィールド)はカンマ(,)で分ける。そのCSVデータを,入れ子(2次元)の配列に変換してみよう。

文字列を指定した区切り文字でエレメントに分けて,配列に変換するには,String.split()メソッドを用いる。第1引数の区切り文字には,もちろん正規表現のパターンが指定できる。

var 配列:Array = 文字列.split(区切り文字)

改行コードのプラットフォームが特定できないCSVデータを,2次元配列に変換するフレームアクションが,スクリプト2だ。このような処理では,CSVデータは外部テキストファイルとされるのが普通だろう。しかし,外部ファイルの読込みはすでに解説した。また,あえて種類の異なる改行コードを混ぜるため,CSVデータをスクリプトで文字列として生成した。

スクリプト2 正規表現によりCSVデータを2次元配列に変換

// フレームアクション
// CSVデータ生成
var products_str:String = "";
products_str += "Web,Flash CS4 Professional,699\r";
products_str += "Web,Dreamweaver CS4,399\r\n";
products_str += "Design,Photoshop CS4,699\n";
products_str += "Design,Illustrator CS4,599";
// CSVデータを2次元配列に変換
var myPattern:RegExp = /\r\n|\r|\n/;
var products_array:Array = products_str.split(myPattern);
var nLength:uint = products_array.length;
for (var i:uint = 0; i < nLength; i++) {
  var product_str:String = products_array[i];
  products_array[i] = product_str.split(",");
}
// 結果確認用
for (var j:uint = 0; j < nLength; j++) {
  var product_array:Array = products_array[j];
  trace(product_array.length, product_array);
}

3種類の改行コードのいずれかを示すパターンは,前述のとおりだ。それをString.split()メソッドの引数に渡し※2),まず改行コードでエレメントに分けて配列にする(products_array)。

つぎに,その変換された配列エレメントすべてをforループで取出し,さらにカンマ(,)で区切った配列に変換して※3),もとの文字列のエレメントと置換える。これで,入れ子の2次元配列ができ上がる。

なお,入れ子の配列は単純にtrace()関数で[出力]しても,すべてカンマ区切りで表示されるので,入れ子構造がわからない。そこで,確認のためforループで順にエレメントの子配列を取出し,そのエレメント数と子配列を[出力]した図4)。

図4 取出したXMLインスタンスのtrace()関数による[出力]

図4 取出したXMLインスタンスのtrace()関数による[出力]

選択制御文字|以外にも「メタ文字」や「メタシーケンス」と呼ばれる特別な文字があり,さまざまな指定ができる。詳しくは,[ヘルプ]を参照してほしい。次回は,マウスイベントについて解説するつもりだ。

※1
最初に検索された文字列だけを置換えたいときは,String.replace()メソッドの第1引数に(正規表現でなくとも)その検索する文字列を直接指定すれば足りる。
※2
String.split()メソッドの第1引数で指定する区切り文字は,参照した文字列の中のすべてがエレメントを切り分ける文字として処理される。したがって,String.replace()メソッドの引数の場合とは異なり,正規表現にg(global)フラグは添えない。
※3
区切り文字に単純な文字列を用いる場合には,正規表現でなく,文字列のまま指定できる。

今回解説した次のサンプルファイルがダウンロードできます。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書

コメント

コメントの記入