![]() |
||
|
基礎解説 スマートな文字列処理のための
|
||
キャプチャ
前編では、正規表現の基礎的なルールを、実例を交えながら解説していった。後編となる今回は、その応用について解説していくことにしよう。まずは、最も利用価値の高い「キャプチャ」について解説する。
前回の冒頭に述べたように、正規表現の用途は単なる検索だけではない。むしろ、文字列の中から正規表現に一致する部分文字列を抜き出す作業でこそ、正規表現のありがたみが感じられる。それでは、部分文字列の抜き出しと正規表現は、どこで結びつくのだろうか。
■正規表現に一致した文字列
前回示したサンプル・プログラム「regex」では、指定した正規表現パターンに一致する文字列が含まれているか否かを調べることしかしていない。これは次のように、Regex.Matchメソッドの戻り値として得られるMatchオブジェクトのSuccessプロパティを参照することで判断可能だった。
Regex regex = new Regex(<正規表現パターンを含む文字列>);
Match m = regex.Match(<被検索文字列>);
if (m.Success) {
// パターンにマッチする文字列が1つ以上含まれていた場合の処理
}
この検索結果が格納されたMatchオブジェクトには、Successプロパティ以外にも多数のプロパティが納められている。そのうちの1つが、パターンにマッチした文字列が格納されているValueプロパティである。このValueプロパティをうまく使えば、文字列の中から特定の部分を簡単に抜き出すことができる。
例えば、与えられた文字列からIPアドレスと思われる部分を抜き出し、これを表示したいとしよう。これはリスト1に示すプログラム「regexip」のように、Valueプロパティを参照すれば簡単に実現できる。
|
|
| リスト1 与えられた文字列からIPアドレスを抜き出すregexip.cs | |
| MatchオブジェクトのValueプロパティには、パターンにマッチした文字列が格納されている。 | |
このregexipプログラムは、以下のように、コマンドラインのパラメータとして与えられた文字列からIPアドレスを抜き出し、表示するプログラムである。
|
|
| リスト1の実行結果例 |
その処理内容はとても簡単だ。文字列から正規表現パターンである、
\d+\.\d+\.\d+\.\d+
を検索し、その結果戻されたValueプロパティを表示しているだけである。前回解説したとおり正規表現で“\d”は、任意の数字に一致するパターンなので、これによりピリオドで区切られた4つの数字を表現できる。各数値が256以上であってもマッチしてしまうので、厳密にはこれでIPアドレスを発見できるとはいいにくいが、その種のチェックは抜き出した後に行った方が簡単だろう。
もし、同じ処理を正規表現を使わずに実現しようとすると、どうなるだろうか。まず文字列の先頭から数字が見付かるまでスキャンする。見付かったら、今度はピリオドが見付かるまで読み進める。このとき、ピリオドよりも先に文字列の末尾に達する可能性も考慮しなければならない。そして、ピリオドが見つかったら、再び数字のチェックを行って……。この繰り返しで、ようやく目的の文字列が取得できる。
今回のサンプルはさほど複雑なパターンではないので、正規表現を使わなくてもそれほどの手間ではないが、それでも正規表現を使ったシンプルさには到底及ばない。それに正規表現ならば、データの書式が変更されても、パターンを修正するだけで対応できるが、コードで実現されていては、たやすい作業にはならないだろう。しかも、書式がどんなに複雑になろうとも、パターンが複雑になるだけで、コードの単純さは保たれるのだから、正規表現で表現できる限りは、もはやコードで文字列解析を行おうとは思わなくなるはずだ。
ところで、いまのリスト1を見ると、正規表現パターン文字列の前に「@」が指定されていることに注目してほしい。もしこの「@」がなければ、このパターン文字列を、
"\\d+\\.\d+\\.\\d+\\.\\d+"
としなければならないのはお分かりだろうか。“¥”を多用することが多い正規表現パターンのリテラル文字列には、文字列の前に「@」を付けてエスケープ処理を無効化する「逐語的文字列リテラル」をお勧めしたい。
ここまで、「部分文字列の抜き出し」と表現してきたが、正規表現では、特定のパターンにマッチした文字列を後で参照できるように保存しておくことを「キャプチャ」と呼ぶ。Regexクラスを使って検索を行うと、パターンに一致した文字列が暗黙的にキャプチャされ、Valueプロパティに格納されるのである。
■すべてのキャプチャ文字列へアクセスする
今度はregexipコマンドを次のように実行してみてほしい。すると、このパラメータにはIPアドレスが2つ含まれているのに、最初に見つかった「192.168.0.0」しか表示されないはずだ。プログラムが1つしか表示しないようになっているのだから当然だ。
regexip "192.168.0.0/24, 172.16.0.0/16"
しかし、このように1回の検索でパターンに一致する文字列が複数個見つかった場合、一致する文字列すべてをキャプチャすることも可能なので、簡単にすべてのIPアドレスを取得できる。ただし、Regex.MatchメソッドはMatchオブジェクトを1つ戻すだけだ。このため、2つ目以降のIPアドレスに対応するMatchオブジェクトへアクセスするには、Match.NextMatchメソッドを使って、キャプチャ・リストをたぐっていかなければならない。
キャプチャされたすべての文字列が表示されるように修正したregexipをリスト2に示す。
|
|
| リスト2 複数個のIPアドレスを抜き出すregexip2.cs | |
| MatchオブジェクトのNextMatchメソッドにより、キャプチャされた2つ目以降のMatchオブジェクトにアクセスすることができる。 | |
まず以前どおりRegex.Matchメソッドを呼び出すと、先頭のIPアドレスに対応するMatchオブジェクトが戻される。その後NextMatchメソッドを呼び出すと、2つ目のIPアドレスに対応するMatchオブジェクトが戻されるので、2つ目のValueプロパティを表示する。もうこれ以上一致する文字列がなくなれば、Successプロパティの値はfalseになるので、ループは終了する。
■グループ
リスト1のregexipでは、IPアドレス全体を1つの文字列として抜き出した。しかしこれでは、各数値を調べるために、再び4つの数字に分割しなければならず、2度手間になってしまう。そこで、IPアドレス全体をキャプチャすると同時に、4つの数字も個々の文字列としてキャプチャされるようにしてみよう。
パターンに一致した文字列の中で、さらに範囲を限定してキャプチャするには、“( 〜 )”によるグループ化を利用する。このメタ文字は、前回ですでに解説したように“|”の範囲限定や、“*”や“+”といった量指定子で繰り返し適用されるパターンのグループ化に利用されるものだが、まったく意味が異なる「キャプチャ範囲の指定」という用途にも利用されるのである。
グループ化を利用して、4つの数字をキャプチャするregexipをリスト3に示す。
|
|
| リスト3 グループ化を利用して、4つの数字をキャプチャするregexip3.cs | |
このリスト3では、まず正規表現パターンが以下のように変更されている。“\d+”がそれぞれ括弧で囲われているのが分かるだろう。
旧)\d+\.\d+\.\d+\.\d+
新)(\d+)\.(\d+)\.(\d+)\.(\d+)
こうしておけば、Valueプロパティから参照できるパターン全体のキャプチャに加えて、括弧で囲われたグループもキャプチャ対象になり、MatchクラスのGroupsプロパティを通してアクセスできるようになる。
Groupsプロパティは、Groupオブジェクトを要素とするGroupCollectionコレクション・クラスのオブジェクトである。パターン内に指定したグループが1つのGroupオブジェクトと1対1に対応し、これがGroupsプロパティに格納される。パターンに指定したグループには、左側から順番に1、2、3とナンバーが振られ、これがGroupsコレクション・プロパティのインデックスとなる。
![]() |
| グループとGroupsプロパティ |
| パターンに指定したグループは、GroupオブジェクトとしてGroupsコレクション・プロパティから取得できる。また、Groups[0]には常にパターン全体に対応するグループが格納される。 |
なお、Groups[0]には常にパターン全体に対応するグループが格納される。明示的にグループが指定されていなくても、パターン全体が暗黙的にグループとして扱われているということだ。
Groupオブジェクトを取得したら、そのメンバであるValueプロパティへアクセスすれば、そのグループでキャプチャされた文字列を参照できる。
| INDEX | ||
| [基礎解説]スマートな文字列処理のための正規表現入門(後編) | ||
| 1.部分文字列のキャプチャ(1) | ||
| 2.部分文字列のキャプチャ(2) | ||
| 3.文字列の置換 | ||
ホワイトペーパー(TechTargetジャパン)
- .NET TIPS - .NET開発のテクニックとヒント集 - (2010/3/11)
− LINQ文で動的にWhere句を組み立てるには?
− GridViewのフッタ行に合計値/平均値を表示するには?
− コレクションをプロパティ値によりグループ化するには? - いくつかのVS 2010 RCの更新 (2010/3/10)
Visual Studio 2010 RC版のIntelliSenseおよびWebデザイナに関するパッチのリリースと、そのほかの問題点についてのお知らせ - C#ラムダ式 基礎文法最速マスター (2010/3/9)
ラムダ式(C#)の基礎文法を、短い説明と簡単なコードで簡潔にまとめる。「ラムダ式、どう書くんだっけ?」という場合の簡易リファレンスとして活用できる - ASP.NET MVC:AJAXによる地図表示/単体テスト (2010/3/8)
ASP.NET MVCを使った、小さいながらも完全なWebアプリケーションの構築手順を最初から最後まで解説。最終部分となるステップ10〜12を公開
|
|
- PowerShell 2.0で始めるWindowsシステム管理
- natテーブルを利用したLinuxルータの作成・2
- ERPの“事業仕訳け”でIT予算をもっと有効に!
- 調査の難しい「OutOfMemoryError」事例、5選
- 組み込みシステム開発における“モデル”とは?
- 西和彦、ビル・ゲイツに会う
- 「事業仕分け」「修正予算」って何?国家予算の全体像
- IT業界職種カタログ(8)ITエデュケーション
- .NET TIPS - .NET開発のテクニックとヒント集 -
- Hyper-Vライブ・マイグレーションの運用ノウハウ
- 構造体の便利な用途、インターフェイス入門
- 3人中2人が間違える!? 片持ちばりの計算をしよう
スキルアップ/キャリアアップ(JOB@IT)
スポンサーからのお知らせ
- - PR -
| 仮想環境の構築とデータ保護の特効薬?! 実績と信頼性の高いパッケージで安心運用 New! |
| 仮想環境のバックアップもこれまでどおり 「まるごと取ってまるごと戻す」簡単運用 |
| おばかアプリ選手権、第4弾開催中!! ムダにカッコよくてくだらない作品求ム! |
| 社内ファイルサーバを“クラウド”に統合 VPN直結「クラウド型ストレージ」を紹介 |
| その数、なんと400台以上! グループ内 サーバの「統合管理」によるメリットは? |
| 美人!? まあまあ? 気になる いやし系!! PV急増で「美人時計」がとった手段とは? |
| .NET編集長が実践する「技術情報検索術」 サンプル・コードを簡単に探す“技”は? |
| 進化を続ける富士通ストレージETERNUS DX 製品開発者の自信を裏付けるものとは何か |
| 運用管理の課題を“2つの観点”から分析 ユーザー満足度の高い「仮想環境」とは? |
- - PR -
お勧め求人情報

**先週の人気講座ランキング**
〜Java編〜
| ◆ | おばかアプリ選手権、第4弾開催中!! ムダにカッコよくてくだらない作品求ム! |
| ◆ | 社内ファイルサーバを“クラウド”に統合 VPN直結「クラウド型ストレージ」を紹介 |
| ◆ | Twitterのアカウントはなぜ突破された? メールによる新手の攻撃手法とその対策 |

| ◆ | もう仮想化のお試しフェイズは終わりだ! Hyper-V 2.0が基幹システムも仮想化 |
| ◆ | 美人!? まあまあ? 気になる いやし系!! PV急増で「美人時計」がとった手段とは? |
| ◆ | クライアント企業から求められる人材 ⇒IT技術と経営戦略を併せ持つ「戦略家」 |

| ◆ | .NET編集長が実践する「技術情報検索術」 サンプル・コードを簡単に探す“技”は? |
| ◆ | 業務効率と情報セキュリティ対策を両立! 手間なく確実に機密情報を守る方法とは? |
| ◆ | 直属上司が海外にいるのエンジニアに見る 【実例】場所に捉われないワークスタイル |

| ◆ | 「仮想化工房」のマイスターが選んだのは VMware、Hyper-V、そしてVirtageだった! |
| ◆ | 進化を続ける富士通ストレージETERNUS DX 製品開発者の自信を裏付けるものとは何か |
| ◆ | 運用管理の課題を“2つの観点”から分析 ユーザー満足度の高い「仮想環境」とは? |

| ◆ | 【CTC事例】約30の基幹システムを統合! 膨大なバッジジョブを制御した方法は? |








