• 検索結果がありません。

正規表現

N/A
N/A
Protected

Academic year: 2021

シェア "正規表現"

Copied!
16
0
0

読み込み中.... (全文を見る)

全文

(1)

■ 正規表現に依りタグを抽出するパターン ■ 使用して居るプログラミング言語に関わらず、文字列内から HTML タグの部分を抽出したり削除した りする事が有る。 其の際、正規表現を使用するが、場合に依っては、確実にHTML タグを判別出来ない場合が有る。 結局、広く知れ渡って居る正規表現パターンが正確に判別出来るが、他のパターンも含めて数種類のパ ターンを検証して観る(正規表現の説明付きで)。 ■ 準備 今回のテストでは、以下の様な文字列を取り扱う事にする。 文字列をダブルクォーテーション( " )で囲んだり、シングルクォーテーション( ' )で囲んだり、 タグの属性値内に更にタグを埋め込んだりして居る。

此の画像<img src="../images/example.png" alt='example.png' title='<img>タグ例' />は<span> テスト画像</span>です。 此の文字列からHTML タグを判別して除去し、以下の様な文字にするパターンを考えて観る事にする。 此の画像はテスト画像です。 ■ パターン 1.テストパターン1(不正確なパターン) <.*?> ・. は、改行を除く任意の1文字。 ・* は、直前の表現の 0 回以上の繰り返しだが、 *? とする事で更に最短一致。 依って、 < と最初の > で囲まれた任意の 0 文字以上の文字列を意味する。 2.テストパターン2(不正確なパターン) <\/?[^>]*> ・\/ は、 / 文字其の物。 / 丈だと別の意味に成るのでエスケープして居る。 ・? は、 直前の正規表現の 0 または 1 回の繰り返し。 ・[ ] は、文字クラス指定。 [ ] 内に列挙した孰れかの1文字。 ・^ は、 [ ] 内の先頭にあれば、 [ ] 内に列挙されて居る指定文字以外の1文字。 ・* は、直前の表現の 0 回以上の繰り返し。

(2)

依って、< と > で囲まれ、 < の次に / が 0 個か 1 個で、残りが > 以外の文字列の事。 言い換えれば、「テストパターン1」の <.*?> と同じに成る。 3.テストパターン3(正確なパターン) <("[^"]*"|'[^']*'|[^'">])*> ・( ) は、正規表現のグループ化。 ・| は、選択(OR)。 ・"[^"]*" は、 " と次の " で囲まれた部分と謂う意味。 此れは、此の部分を1個の塊と看做す為。 ・'[^']*' は、 ' と次の ' で囲まれた部分と謂う意味。 此れは、此の部分を1つの塊と看做す為。 ・[^'">] は、 ", ', > 以外の1文字。 " と " で囲まれた部分や ' と ' で囲まれた部分を1個の塊と看做して居るのに、更に " や ' が存 在した場合は HTML タグではない。 亦、 > を除去するのは最短一致させる為で有る。 4.テストパターン4(正確なパターン) <(".*?"|'.*?'|[^'"])*?> 此れは「テストパターン3」の正規表現を書き換えた丈の物なので、此れも正確に HTML タグを判別 出来る。

(3)

■ 正規表現の基本(.NET Framework 編) ■

此処では.NET Framework の正規表現に付いて基本を極く簡単に(主に正規表現パターンに付いて)説 明する。猶.NET Framework の正規表現は Perl5 の正規表現に対応する様にデザインされて居ると謂う 事なので、Perl の正規表現を理解して居れば問題無い。 ■ 正規表現で何が出来るか 正規表現は、文字列を検索する為に使用する。正規表現を使うと、可成り複雑な検索が可能で有る。正 規表現を利用する主なケースには以下の様な物が挙げられる。 ・文字列内に指定されたパターンと一致する部分が有るか調べる。 例えば、入力された文字列が電子メールアドレスとして適当か調べる等。 ・文字列から指定されたパターンと一致する部分を検索、抽出する。 例えば、文字列内に有るURL の部分をすべて抜き出す等。 ・文字列から指定されたパターンと一致する部分を探して別の文字列に置換する。 例えば、文字列内に有るURL にリンク(<a>タグ)を付けたり、HTML のタグを削除する等。 補足:此等以外にも、文字列を分割して配列にする場合にも使用出来る。此の場合は、Regex.Split メ ソッドを使う。 ■ パターンは何の様に書けば良いか? 「斯んな文字列が出て来る部分を探して」と謂う事を指定するには、其れを表現したパターンを書く必 要が有る。適切なパターンを書ける様に成る事が、正規表現を勉強する最大の目標と成るだろう。 パターンは、ファイルの検索等で使用される「*」や「?」等のワイルドカードを御存じの方ならば、此 れと同じ様な物だと思って結構で有る。 例えば、文字列から或る郵便番号と一致する部分を探し度いとする。其の郵便番号が決まって居り、 「123-4567」で有るならば、パターンは「123-4567」の儘で良い。但し、此の様に探し度い文字列が 決まって居るならば、正規表現を使う意味が無い。 決まった郵便番号ではなく、郵便番号っぽい文字列を探し度い、詰り、「何等かの数字が3 つ続き、-(ダ ッシュ)が挟まり、亦数字が4 つ続く文字列」を探し度いと謂う事で有れば、正規表現が役に立つ。此 の様な場合、書く可きパターンは、「¥d¥d¥d-¥d¥d¥d¥d」と成る(別の書き方も出来る)。詰り、「¥d」 は「何等かの数字1 文字」を意味する。 此の様に正規表現のパターンでは、「¥」等の特定の文字列が特別な意味を持って居る。此の様な特別な 意味を持つ文字を「メタ文字」(メタキャラクタ)と呼ぶ。 ■ 簡単な例

.NET で正規表現を扱うには、Regex クラスを使う。以下に Regex クラスを使って文字列の検査、抽出、 置換を行う簡単な例を示す。

(4)

Visual Basic ' TextBox1 に郵便番号っぽい文字列が含まれて居るか調べる If System.Text.RegularExpressions.Regex.IsMatch( _ TextBox1.Text, "¥d¥d¥d-¥d¥d¥d¥d") Then Console.WriteLine("郵便番号が含まれて居る") End If ' TextBox1 内の郵便番号っぽい文字列を総て抽出する Dim mc As System.Text.RegularExpressions.MatchCollection = _ System.Text.RegularExpressions.Regex.Matches( _ TextBox1.Text, "¥d¥d¥d-¥d¥d¥d¥d")

For Each m As System.Text.RegularExpressions.Match In mc Console.WriteLine(m.Value) Next ' TextBox1 内の郵便番号っぽい文字列の"-"を削除して、【】で囲む TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( _ TextBox1.Text, "(¥d¥d¥d)-(¥d¥d¥d¥d)", "【$1$2】") C# // TextBox1 に郵便番号っぽい文字列が含まれて居るか調べる if (System.Text.RegularExpressions.Regex.IsMatch( TextBox1.Text, @"¥d¥d¥d-¥d¥d¥d¥d")) { Console.WriteLine("郵便番号が含まれて居る"); } // TextBox1 内の郵便番号っぽい文字列を総て抽出する System.Text.RegularExpressions.MatchCollection mc = System.Text.RegularExpressions.Regex.Matches( TextBox1.Text, @"¥d¥d¥d-¥d¥d¥d¥d"); foreach (System.Text.RegularExpressions.Match m in mc) { Console.WriteLine(m.Value); } // TextBox1 内の郵便番号っぽい文字列の"-"を削除して、【】で囲む TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( TextBox1.Text, @"(¥d¥d¥d)-(¥d¥d¥d¥d)", "【$1$2】"); ■ メタ文字一覧 以下に良く使われるメタ文字と其の意味を紹介する。詳しくは MSDN の「正規表現言語要素」を参照 され度い。

(5)

或る1 文字を表す文字(アトム) 文字 説明 使用例 .(ピリオド) 改行文字(¥n)以外の任意の一文字。(但し [] 内ではピリオド文 字。) 「.」 「」内に任意の1 文字が 有る箇所にマッチ ¥s 空白文字。改行文字、タブ文字、半角/全角スペース文字等。 [¥f¥n¥r¥t¥v¥x85¥p{Z}]と同じ。 (ちなみに ¥S は ¥s 以外の文字を表す。) Visual¥sBasic Visual と Basic の間に 空白文字が1 文字有る箇 所にマッチ ¥d 0 から 9 までの数字。全角を含む。¥p{Nd}と同じ。 (ちなみに ¥D は ¥d 以外の文字を表す。) VB¥d VB の後に数字が 1 文字 有る箇所にマッチ ¥w 単語に使用される文字。アルファベット、数字、アンダーバー (_) 、 ひ ら が な 、 カ タ カ ナ 、 漢 字 等 。 [¥p{Ll}¥p{Lu}¥p{Lt}¥p{Lo}¥p{Nd}¥p{Pc}¥p{Lm}]と同じ。 (因みに ¥W は ¥w 以外の文字を表す。) 「¥w」 「」内に単語に使用され る文字が1 文字が有る箇 所にマッチ ¥r キャリッジリターン。¥u000D と同じ。 ¥r¥n Windows の 改 行 文 字 (CRLF)にマッチ ¥n ラインフィード(改行文字)。¥u000A と同じ。 ¥r¥n Windows の 改 行 文 字 (CRLF)にマッチ ¥t タブ。¥u0009 と同じ。 ¥n¥t 改行文字(¥n)の後にタ ブが続く箇所にマッチ ¥¥ 文字の前に ¥ を付けると、其の文字。メタ文字の機能を無効 にするときに使う。(ある文字列内のメタ文字を総て ¥ でエス ケープするには、Regex.Escape メソッドを使うと良い。) DOBON¥.NET DOBON.NET にマッチ [ ] []内のどれか 1 文字。[abc]ならば、a か b か c。 VB[2456] VB の後に 2 か 4 か 5 か 6 が続く箇所にマッチ [^ ] [^]内の文字以外の 1 文字。[^abc]ならば、a か b か c 以外の文 字。 「[^「」]」 「」内に「」以外の1 文 字が有る箇所にマッチ [ - ] 連続した文字範囲の1 文字。[0-9]ならば、数字 1 文字。[a-zA-Z] ならば、アルファベット1 文字。 VB[24-6] VB の後に 2 か 4 か 5 か 6 が続く箇所にマッチ ¥u0000 4 桁の 16 進数で表される Unicode 文字。 [¥uFF61-¥uFF9F] 半角カナ文字の1 文字に マッチ(詳細) ¥x00 2 桁の 16 進数で表される ASCII 文字。 [¥x20-¥x7F] 半角英数記号文字(0x20 ~0x7F)の 1 文字にマッ チ

(6)

文字列内の位置を表す文字(アトミックゼロ幅アサーション、アンカー、位置指定子) 此処で紹介するメタ文字は、文字列内の位置を表現した物で有る。文字とマッチする訳では無い。 【此処から】 文 字 説明 使用例 ^ 文字列の先頭。 ^¥d 先頭に有る数字 1 文字に マッチ $ 文字列の末尾。但し、文字列の末尾が ¥n の時は、其の前と一致。(末尾が ¥n でも末尾で一致させるには、¥z を使う。) ¥d$ 末尾に有る数字 1 文字に マッチ ¥b 単語の境界(¥w と ¥W の間)と一致。(但し [] 内ではバックスペー ス文字。) (因みに ¥B は ¥b 以外の境界を表す。) ¥bVB¥b VB が単語として現れる 箇所にマッチ 文字の繰り返しを表す文字(量指定子) 此処で紹介する量指定子は、文字(または、グループ)の繰り返しを表現する物で有る。最長マッチと 最短マッチの違いは非常に重要ですが、此れに付いては後述する。 文字 説明 使用例 * 直前の文字が0 回以上繰り返す。 <[^>]*> <>で囲まれた箇所にマッチ + 直前の文字が1 回以上繰り返す。 <[^>]+> <>内に 1 文字以上有る箇所 にマッチ ? 直前の文字が0 回または 1 回繰り返す。 -?¥d+ マイナスが付いた数字、ある いは付かない数字にマッチ {n,m} 直前の文字が n 回以上 m 回以下繰り返す。 ¥d{2,6} 数字が2 文字以上 6 文字以下 続いて居る箇所にマッチ {n} 直前の文字がn 回繰り返す。 ¥d{6} 数字が6 文字続いて居る箇所 にマッチ {n,} 直前の文字が n 回以上繰り返す。 ¥d{8,} 数字が8 文字以上続いて居る 箇所にマッチ *? 最短マッチで、0 回以上の繰り返し。? は *、+、?、{} の後につけ て最短マッチを表す事が出来る。最短マッチと最長マッチに付いて は、後述。 <.*?> <>で囲まれた箇所にマッチ

(7)

選択、グループ化等を表す文字 此処で紹介するグループ化を使用する主なケースとしては、論理和による選択を行う場合や、前方参照 (後述)やMatch.Groups プロパティでの抽出を行い度い場合等が挙げられる。 .NET Framework にはグループに名前(あるいは番号)を付ける事が出来ると謂う特徴が有る。グルー プに名前を付けても付けなくても、グループには1 から連番で番号が付けられる(番号 0 はパターン全 体です)。 此処では先読み、後読みアサーションも紹介して居るが、此等は少し高度で有る。ですので初心者の方 は此等を無視していただいても構いませんが、知っておくと可成り役に立つ。 因みに、後読みアサーションのパターンとマッチする文字列は固定長でなければならないとするエンジ ンが多いですが、.NET Framework では此の様な制限が無い。 文字 説明 使用例 | | で区切られた文字列の孰れか(論 理和)。 リンゴ|りんご|林檎 リンゴ または りんご または 林檎 にマッチ ( ) グループ化する箇所。 山田(太郎|花子) 山田太郎 または 山田花子 にマッチ (?<name> ) グループに名前(あるいは番号)を 付ける。(因みに、< > の代わりに ' で括る事も出来る。) VB(?<ver>¥d) VB の後に数字が有る箇所にマッチし、数字を"ver" と謂うグループ名でキャプチャ (?: ) キャプチャしないグループ。 山田(?:太郎|花子) 山田太郎 または 山田花子 にマッチするが、太郎 ま たは 花子 をキャプチャしない (?= ) 直後に此のパターンが現れる事を確 認する(ゼロ幅の肯定的先読みアサ ーション)。 ¥d+(?=%) 後ろに % が続く数字の連続にマッチ。但し、% はマ ッチした箇所に含まれないし、グループとしてキャプ チャもされない。 (?! ) 直後に此のパターンが現れない事を 確認する(ゼロ幅の否定的先読みア サーション)。 ¥d+(?!%) 後ろに % が来ない数字の連続にマッチ。 (?<= ) 直前に此のパターンが現れる事を確 認する(ゼロ幅の肯定的後読みアサ ーション)。 (?<=¥¥)¥d+ ¥ に続く数字の連続にマッチ。但し、¥ はマッチし た箇所に含まれないし、グループとしてキャプチャも されない。 (?<! ) 直前に此のパターンが現れない事を 確認する(ゼロ幅の否定的後読みア サーション)。 (?<!¥¥)¥d+ 前に ¥ がない数字の連続にマッチ。 前方参照(後方参照)を表す文字 グループ化してキャプチャした文字列を後から参照する事が出来る。此れが前方参照(後方参照)で有 る。此れに依って、キャプチャした文字列をパターンに埋め込む様な事が出来る。

(8)

文字 説明 使用例 ¥number 番号が number のグループと一致した文字列。 <(H¥d)>.*?</¥1> <H>タグで囲まれた箇所にマッ チ ¥k<name> 名前がname のグループと一致した文字列。(因みに、< > の代わりに ' で括る事も出来る。) <(?<tag>H¥d)>.*?</¥k<tag>> <H>タグで囲まれた箇所にマッ チ 置換パターンで使用出来る特殊文字 前方参照(後方参照)と同じ様に置換パターン内で以下の様な特殊文字を使用する事が出来る。 文字 説明 $number 番号が number のグループと一致した文字列。 ${name} 名前が name のグループと一致した文字列。 $& パターン全体と一致した文字列。 良く使われるオプション オプションを指定する事も出来る。オプションを指定するとメタ文字の意味が多少変わる物も有 る。.NET ではオプションを指定するのに RegexOptions 列挙体を使用する(インラインで使用する方 法も有るが、此処では紹介しません)。以下に良く使われる重要なオプションを示す。 RegexOptions 列挙 体のメンバ 説明 IgnoreCase 大文字と小文字を区別しない。 Singleline .(ピリオド)の意味を変更し、¥n を含めた総ての文字と一致する様にする。 Multiline ^ と $ の意味を変更し、文字列全体の先頭と末尾だけでなく、行の先頭と末尾に も一致する様にする。具体的には、^ は ¥n の後、$ は ¥n の前(改行文字が ¥r¥n であったとしても)にも一致する様に成る。^ と $ の代わりに ¥A と ¥Z を使用すると、Multiline の影響を受けずに文字列全体の先頭と末尾に一致させる 事が出来る。 ECMAScript ECMAScript 準拠の動作とする。此の事で、一部のメタ文字の意味が変更される。 例えば、 ¥w は [a-zA-Z_0-9] と同じに、 ¥s は [^ ¥f¥n¥r¥t¥v] と同じに、 ¥d は [0-9] と同じに成る。其の他詳しくは、「ECMAScript と標準一致の動作の比 較」。 CultureInvariant 言語の違いを無視する。 Compiled 正規表現をコンパイルして実行速度を上げる。但し、起動時間は長く成る。 最長マッチと最短マッチ 最長マッチと最短マッチの違いは非常に重要ですので、此処で説明しておきます。

(9)

例えば、カギかっこ(「」)で囲まれた文字列を抽出する為に次の様なパターン(コード)を書いたとす る。 Visual Basic Dim mc As System.Text.RegularExpressions.MatchCollection = _ System.Text.RegularExpressions.Regex.Matches( _ TextBox1.Text, "「.*」") C# System.Text.RegularExpressions.MatchCollection mc = System.Text.RegularExpressions.Regex.Matches( TextBox1.Text, @"「.*」"); 此の様なパターンでは、カギかっこが複数あった場合、問題が起こります。例えば、TextBox1 に"・・・ 「あ」、「い」、「う」・・・"と入力されて居るならば、マッチする文字列は、"「あ」、「い」、「う」"の 1 つだけで有る。"「あ」"、"「い」"、"「う」"の 3 か所にマッチする様にするには、パターンを"「.*?」 "と書き換えます。詰り、"*"の後ろに"?"を付けて、最短マッチにする。"?"を付けないと最長マッチに成 るので、一致する箇所が最も長く成る様な方法で検索が行われます。 因みに上記の様な例で有れば、最短マッチにしなくても、"「[^」]*」"と書けばほぼ同じ事が出来る。 参考: .NET Framework の正規表現 正規表現言語要素 ■ 正規表現に依るタグ抽出(.NET Framework 編) ■ 正規表現を使って文字列の検索し、検索された文字列を取得するには、Regex クラスと Match メソッ ド(またはMatchs メソッド)を使用する。一致した要素は Match オブジェクトとして返されます。 ■ メールアドレスを抽出する 次の例ではTextBox1 に入力された文字列からメールアドレスっぽい文字列を総て検索し、表示する。 此処で使用して居る正規表現パターンは、「Regular-Expressions.info」で紹介されて居る物で有る。 Visual Basic 'Regex オブジェクトを作成

Dim r As New System.Text.RegularExpressions.Regex( _ "¥b[A-Z0-9._%+-]+@[A-Z0-9.-]+¥.[A-Z]{2,4}¥b", _

System.Text.RegularExpressions.RegexOptions.IgnoreCase) 'TextBox1.Text 内で正規表現と一致する対象を 1 つ検索

Dim m As System.Text.RegularExpressions.Match = r.Match(TextBox1.Text) '次の様に一致する対象を総て検索する事も出来る

'Dim mc As System.Text.RegularExpressions.MatchCollection = _ ' r.Matches(TextBox1.Text)

While m.Success

(10)

Console.WriteLine(m.Value) '次に一致する対象を検索 m = m.NextMatch() End While C# //Regex オブジェクトを作成 System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex( @"¥b[A-Z0-9._%+-]+@[A-Z0-9.-]+¥.[A-Z]{2,4}¥b", System.Text.RegularExpressions.RegexOptions.IgnoreCase); //TextBox1.Text 内で正規表現と一致する対象を 1 つ検索 System.Text.RegularExpressions.Match m = r.Match(TextBox1.Text); //次の様に一致する対象を総て検索する事も出来る //System.Text.RegularExpressions.MatchCollection mc = r.Matches(TextBox1.Text); while (m.Success) { //一致した対象が見つかったときキャプチャした部分文字列を表示 Console.WriteLine(m.Value); //次に一致する対象を検索 m = m.NextMatch(); } ■ HTML 内の<H>タグを抽出する 次にグループ化の例を示す。正規表現でグループ化を指定するには、「(?<(数字または名前)>)」の様 にする。正規表現に一致したグループはMatch クラスの Groups プロパティで取得出来る。猶 MSDN には、「HREFS のスキャン」と謂う例や、「URL 情報の抽出」と謂う例が紹介されて居る。 以下にTextBox1 に入力された文字列を検索して、HTML の H タグ(H1、H2、H3、...)と其の部分 のテキストを抽出する例を示す。先程の例ではMatch メソッドを使っていましたが、今回は Matches メソッドを使ってみます。もちろん先ほどと同じ様にMatch メソッドを使っても構いません。 Visual Basic '正規表現パターンとオプションを指定して Regex オブジェクトを作成 Dim r As New System.Text.RegularExpressions.Regex( _

"<(h[1-6])¥b[^>]*>(.*?)</¥1>", _ System.Text.RegularExpressions.RegexOptions.IgnoreCase Or _ System.Text.RegularExpressions.RegexOptions.Singleline) 'TextBox1.Text 内で正規表現と一致する対象を総て検索 Dim mc As System.Text.RegularExpressions.MatchCollection = _ r.Matches(TextBox1.Text)

For Each m As System.Text.RegularExpressions.Match In mc '正規表現に一致したグループの文字列を表示

(11)

"タグ内の文字列:" + m.Groups(2).Value) Next C# //正規表現パターンとオプションを指定して Regex オブジェクトを作成 System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex( @"<(h[1-6])¥b[^>]*>(.*?)</¥1>", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline); //TextBox1.Text 内で正規表現と一致する対象を総て検索 System.Text.RegularExpressions.MatchCollection mc = r.Matches(TextBox1.Text); foreach (System.Text.RegularExpressions.Match m in mc) { //正規表現に一致したグループと位置を表示 Console.WriteLine("タグ:" + m.Groups[1].Value + "¥n タグ内の文字列:" + m.Groups[2].Value + "¥n タグの位置:" + m.Groups[1].Index); } ■ HTML 内のリンクを抽出する

下の例はTextBox1 に入力された文字列を検索して、<a href="...">...</a>でリンクされて居るリンク先

のURL とリンクされて居る文字列を総て調べ、結果を出力する物で有る。今までの例ではインスタン スメソッドのMatches(あるいは Match)を使用していましたが、今回は静的メソッドを使ってみます。 Visual Basic 'TextBox1.Text 内で正規表現と一致する対象を総て検索 Dim mc As System.Text.RegularExpressions.MatchCollection = _ System.Text.RegularExpressions.Regex.Matches( _ TextBox1.Text, _ "<a¥s+[^>]*href¥s*=¥s*(?:(?<quot>[""'])(?<url>.*?)¥k<quot>|" + _ "(?<url>[^¥s>]+))[^>]*>(?<text>.*?)</a>", _ System.Text.RegularExpressions.RegexOptions.IgnoreCase Or _ System.Text.RegularExpressions.RegexOptions.Singleline) For Each m As System.Text.RegularExpressions.Match In mc '正規表現に一致したグループを表示 Console.WriteLine("URL:{0}", m.Groups("url").Value) Console.WriteLine("テキスト:{0}", m.Groups("text").Value) Next C# //TextBox1.Text 内で正規表現と一致する対象を総て検索 System.Text.RegularExpressions.MatchCollection mc = System.Text.RegularExpressions.Regex.Matches( TextBox1.Text, @"<a¥s+[^>]*href¥s*=¥s*(?:(?<quot>[""'])(?<url>.*?)¥k<quot>|" + @"(?<url>[^¥s>]+))[^>]*>(?<text>.*?)</a>",

(12)

System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline); foreach (System.Text.RegularExpressions.Match m in mc) { //正規表現に一致したグループを表示 Console.WriteLine("URL:{0}", m.Groups["url"].Value); Console.WriteLine("テキスト:{0}", m.Groups["text"].Value); } ■ 同じ番号(名前)のグループが複数有る時 同じ番号のグループに複数の箇所が一致する場合が有る。例えば、「(¥d)+」と謂うパターンで「123」 を検索すると、グループ1 に「1」、「2」、「3」の 3 つの文字が一致する。亦、.NET Framework ではグ ループに名前や番号を付ける事が出来るので、同じ名前や番号のグループを複数作る事も出来る。此の 様に同じ名前や番号のグループが複数あった場合どう成るかに付いて簡単に説明する。 此の様な場合、グループの値としては最後に一致したグループの値が入ります。しかし、キャプチャさ れた総ての値はグループのCaptures コレクションに格納されて居る。 具体的にどう成るか、例を示す。以下の例では、パターンを「(¥d)+」とし、「123」と謂う文字列を検 索して居る。 Visual Basic

Dim r As New System.Text.RegularExpressions.Regex("(¥d)+")

Dim mc As System.Text.RegularExpressions.MatchCollection = r.Matches("123") For Each m As System.Text.RegularExpressions.Match In mc

For i As Integer = 0 To m.Groups.Count - 1

Console.WriteLine("グループ{0}:{1}", i, m.Groups(i)) For l As Integer = 0 To m.Groups(i).Captures.Count - 1

Console.WriteLine(" キャプチャ{0}:{1}", l, m.Groups(i).Captures(l).Value) Next Next Next C# System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex( @"(¥d)+"); System.Text.RegularExpressions.MatchCollection mc = r.Matches("123"); foreach (System.Text.RegularExpressions.Match m in mc) {

for (int i = 0; i < m.Groups.Count; i++) {

Console.WriteLine("グループ{0}:{1}", i, m.Groups[i]); for (int l = 0; l < m.Groups[i].Captures.Count; l++) {

(13)

} } } 此のプログラムを実行すると、以下の様に表示されます。 グループ0:123 キャプチャ 0:123 グループ1:3 キャプチャ 0:1 キャプチャ 1:2 キャプチャ 2:3 此の結果の様に、グループ1 には最後にキャプチャされた「3」が入りますが、グループ 1 の Captures にはキャプチャされた総ての結果が入って居る。 ■ 正規表現に依る文字列置換(.NET Framework 編) ■ 正規表現を使って文字列の置換を行うには、Regex クラスの Replace メソッドを使用する。此処ではい くつかの具体例を紹介する。MSDN にも「日付形式の変更」と謂う例が載って居るので、そちらも参 考にしてください。 ■ URL にリンクを付ける

次の例ではTextBox1 に入力された文字列内の URL に自動的にリンク(<a>タグ)をつけて、TextBox1 に結果を表示して居る。 Visual Basic 'URL にリンクを付ける TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( _ TextBox1.Text, _ "s?https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+", _ "<a href=""$&"">$&</a>") C# //URL にリンクを付ける TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( TextBox1.Text, @"s?https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+", "<a href=¥"$&¥">$&</a>"); ■ 行末の空白文字を削除する 次の例ではTextBox1 に入力された文字列から総ての行末の空白文字(半角スペース、全角スペース、 タブ)を削除して居る。先程の例では静的メソッドのReplace を使いましたが、此処ではインスタンス メソッドを使ってみます。 Visual Basic 'パターンを指定して Regex オブジェクトを作成

(14)

Dim r As New System.Text.RegularExpressions.Regex("[ ¥t]+(?=¥r?¥n|$)") '行末の空白文字を削除 TextBox1.Text = r.Replace(TextBox1.Text, "") C# //パターンを指定して Regex オブジェクトを作成 System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"[ ¥t]+(?=¥r?¥n|$)"); //行末の空白文字を削除 TextBox1.Text = r.Replace(TextBox1.Text, ""); 因みに、パターンを"[ ¥t]+$"として、RegexOptions.Multiline オプションを付けたとしても、改行 文字が"¥r¥n"ならば、行末の空白文字を削除する事は出来ません。なぜならば、$ は ¥n の前、 ¥r の 後ろとマッチする為で有る。 ■ 行頭に引用記号を挿入する 次の例ではTextBox1 に入力された文字列の行頭に「< 」を挿入して居る。パターンの「^」は 0 幅で すが、置換に利用出来る。 Visual Basic '行頭に引用記号"> "を挿入する TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( _ TextBox1.Text, _ "^", _ "> ", _ System.Text.RegularExpressions.RegexOptions.Multiline) C# //行頭に引用記号"> "を挿入する TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( TextBox1.Text, "^", "> ", System.Text.RegularExpressions.RegexOptions.Multiline); ■ 連続する同じ行を削除する 次の例ではTextBox1 に入力された文字列から連続する同じ行を削除して居る。詰り、同じ内容の行が 連続して居る場合、其れを1 行だけにする。 Visual Basic '連続する同じ行を削除 TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( _ TextBox1.Text, _ "^(.*)(¥r?¥n¥1)+$", _ "$1", _ System.Text.RegularExpressions.RegexOptions.Multiline) C# //連続する同じ行を削除 TextBox1.Text = System.Text.RegularExpressions.Regex.Replace(

(15)

TextBox1.Text, @"^(.*)(¥r?¥n¥1)+$", "$1", System.Text.RegularExpressions.RegexOptions.Multiline); ■ 日付のフォーマットを変更する 「2000/10/22」の様に「/」で区切られて居る形式の日付を「2000 年 10 月 22 日」と変更する例を示す。 Visual Basic '"2000/10/22"の様な形式を"2000 年 10 月 22 日"の様に変換する TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( _ TextBox1.Text, _ "(?<year>(?:¥d¥d)?¥d¥d)/(?<month>¥d¥d?)/(?<day>¥d¥d?)", _ "${year}年${month}月${day}日") C# //"2000/10/22"の様な形式を"2000 年 10 月 22 日"の様に変換する TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( TextBox1.Text, @"(?<year>(?:¥d¥d)?¥d¥d)/(?<month>¥d¥d?)/(?<day>¥d¥d?)", "${year}年${month}月${day}日"); ■ MatchEvaluator デリゲートを使用する MatchEvaluator デリゲートを使用すれば、もっと複雑な置換が可能で有る。 次の例では、日付の部分を1 日増やした日付と置換して居る。 Visual Basic 'Button1 の Click イベントハンドラ

Private Sub Button1_Click(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles Button1.Click '日付の部分("2000/10/22"の様な形式)を 1 日増やす

TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( _ TextBox1.Text, _

"(?<year>(?:¥d¥d)?¥d¥d)/(?<month>¥d¥d?)/(?<day>¥d¥d?)", _

New System.Text.RegularExpressions.MatchEvaluator(AddressOf IncrementDay)) End Sub

'MatchEvaluator デリゲートメソッド Private Shared Function IncrementDay( _

ByVal m As System.Text.RegularExpressions.Match) As String Dim dt As DateTime 'マッチした文字列を日時に変換 If DateTime.TryParse(m.Value, dt) Then '1 日増やす Return dt.AddDays(1).ToShortDateString() Else

(16)

Return m.Value End If

End Function

C# //Button1 の Click イベントハンドラ

private void Button1_Click(object sender, System.EventArgs e) { //日付の部分("2000/10/22"の様な形式)を 1 日増やす TextBox1.Text = System.Text.RegularExpressions.Regex.Replace( TextBox1.Text, @"(?<year>(?:¥d¥d)?¥d¥d)/(?<month>¥d¥d?)/(?<day>¥d¥d?)", new System.Text.RegularExpressions.MatchEvaluator(IncrementDay)); } //MatchEvaluator デリゲートメソッド

private static string IncrementDay(System.Text.RegularExpressions.Match m) { DateTime dt; //マッチした文字列を日時に変換 if (DateTime.TryParse(m.Value, out dt)) { //1 日増やす return dt.AddDays(1).ToShortDateString(); } else { return m.Value; } }

参照

関連したドキュメント

When value of &lt;StThr[3:0]&gt; is different from 0 and measured back emf signal is lower than &lt;StThr[3:0]&gt; threshold for 2 succeeding coil current zero−crossings (including