「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。 -[[戻る>その他、開発の色々]] * 目次 [#k7393046] #contents *概要 [#j3903cec] **正規表現とは、 [#o987188c] 正規表現(regular expression) -「文字列の集合」を「文字列の特徴 / パターンを表現する文字列」で表現する方法の一つであり、 -正規表現によるパターン マッチを行なうことで、各種文字列処理(検索、置換)を行なうときに利用する非手続き言語。 **用途 [#q8bdf40b] 正規表現のパターン マッチを使用すれば、例えば、次のような処理に利用可能である。 +文字列の「特徴」(パターン)に一致するか検証する。 --用途:入力チェックなどに使用可能 --API:Regex.IsMatch() メソッドを使用する(型.Parse( ) メソッドの強化版)。 +文字列の「特徴」(パターン)に一致する部分文字列を抜き出す。 --用途:全文検索処理などに使用可能 --API:Regex.Matchs() メソッドを使用する(String.IndexOf( ) メソッドの強化版)。 +文字列の「特徴」(パターン)に一致する部分文字列を置換する。 --用途:置換(付加、削除、書式変更など)に使用可能 --API:Regex.Replace() メソッドを使用する(String.Replace( ) メソッドの強化版)。 +文字列の「特徴」(パターン)に一致する文字列で文字列分割する。 --用途:文字列分割処理に使用可能 --API:Regex.Split() メソッドを使用する(String.Split( ) メソッドの強化版)。 +.etc **ライブラリ [#c5e3b59b] 現在では、Perl、PHP、Java、JavaScript、.NET、Python、Rubyなど、~ 広く様々なランタイムに実装されており、テキスト エディタ、ワード プロセッサをはじめとする、~ アプリケーション ソフトの検索・置換機能などで利用することもできるようになっている。 **方言 [#be2b1035] ただし、ソフトウェアによって「方言」や利用できない機能があるため、注意が必要である。 -言語やアプリケーションで細部の仕様が異なっているが、POSIXにより標準規格も定められそれに準拠するものも増えてきている。 -.NETの正規表現は、Perl5の正規表現に対応するようにデザインされている。 -また、[[APIオプション>#q6a71c4d]]を指定することによってECMAScript(JavaScript等)と同様の正規表現に対応するように動作を変更できる。 *正規表現の書き方 [#n9655e29] 正規表現は、 -通常の文字と、 -「メタ文字」 -「エスケープ文字」 組み合わせて表記される。 正規表現の書き方を習得するには、これらの要素を覚える必要がある。 **メタ文字 [#p7d325cd] 特別な意味を持った記号。 ***区分 [#mf2da4d7] -[[角括弧(文字グループ)>#ue25e11a]] -[[丸括弧(各構成体)>#b0b52452]] -[[キャプチャの利用>#bff3e596]] --[[前後方参照>#s8e591e9]] --[[文字列置換>#r4700117]] -[[最長 / 最短マッチ>#c940097d]] --[[最長マッチ>#y2259122]] --[[最短マッチ>#vec3cd85]] ***動作 [#d3fb549f] -実際にどのように動作するかは、[[APIオプション>#q6a71c4d]]を理解する必要がある。 -([[APIオプション>#q6a71c4d]]の指定によって、上記要素の意味が変更されることがあるため) ***一覧 [#i1357d54] 以下が、.NET Frameworkの正規表現で使用できるメタ文字。 |項番|区分|メタ文字|説明 / 注釈|h |1|>|位置指定子|「 ^ 」、「 $ 」の両方を指定することで全文のマッチを強制できる。&br;エスケープ文字に含まれる位置指定子もある。| |1-1||^|文字列の先頭を表す(中間からのマッチを拒否)&br;※ 正規表現、部分式の先頭のものしかメタ文字として認識されない。| |1-2||$|文字列の末尾を表す(中間からのマッチを拒否)&br;※正規表現、部分式の終端のものしかメタ文字として認識されない。| |2|>|代替構成体|詳細はxxx節を参照| |2-1||||「|」 で区切られた文字列のいずれか。&br;通常、下記、5-2の丸括弧と併用するが、単独で利用することも可能。| |3|>|量指定子|正規表現での量指定子&br;http://msdn.microsoft.com/ja-jp/library/3206d374.aspx| |3-1||*|前の文字列が 0 回以上連続にマッチする( = {0,})。| |3-2||+|前の文字列が 1 回以上連続にマッチする( = {1,})。| |3-3||?|前の文字列が 0 or 1 回マッチする( = {0,1})。| |3-4||{n}|前の文字列がn回連続にマッチする。| |3-5||{n,}|前の文字列がn回以上連続にマッチする。| |3-6||{n, m}|前の文字列がn-m回連続にマッチする。| |3-7||*? ,etc.|*、+、?、{ } の後に「 ? 」をつけて「[[最短マッチ>#vec3cd85]]」を表す。| |4|>|文字クラス|正規表現での文字クラス&br;http://msdn.microsoft.com/ja-jp/library/20bw873z.aspx| |4-1||. (ピリオド)|改行(\n)以外の任意の1文字| |4-2||[ ] (角括弧)|下記、5-1に該当| |4-3||\s|スペースやタブなどの空白文字| |4-4||\S|\S以外([^\s]と同義)| |4-5||\d|10進数([0-9]と同義)| |4-6||\D|\d以外([^\d]と同義)| |4-7||\w|単語に使用される任意の文字&br;([\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}\p{Lm}]と同義)| |4-8||\W|\w以外([^\w]と同義)| |5|>|括弧|| |5-1||[ ] 角括弧&br;詳細は「[[角括弧による文字グループ>#ue25e11a]]」を参照。|下記の角括弧内に指定した文字にマッチする。&br;・文字範囲(Unicodeの文字コード表)、&br;・文字グループ&br;以下は、角括弧内でのみ使われる特殊なメタ文字である。&br;・「 - 」:範囲指定 、例えば[a-z]で半角英小文字の文字グループを表す。&br;・「 ^ 」:先頭で使われたとき、「含まれない」と条件を反転する。| |5-2||( ) 丸括弧&br;詳細は「[[丸括弧による構成体>#b0b52452]]」を参照|丸括弧内に指定した文字、文字範囲、文字グループに完全にマッチする。&br;グループ化構成体、代替構成体、その他の構成体を構成する。| |6|>|日本語文字クラス(\p{xxxx})|.NET TIPS 文字列のひらがな/カタカナをチェックするには? - C# - @IT&br;http://www.atmarkit.co.jp/fdotnet/dotnettips/054iskana/iskana.html| |6-1||\p{IsHiragana}|平仮名| |6-2||\p{IsKatakana}|片仮名| |6-3||\p{IsCJKUnifiedIdeographs}|漢字| |6-4||P{xxxx}|p{xxxx}以外| **エスケープ文字 [#ec021b89] エスケープ文字 には次のようなものがある。 |項番|区分|文字のエスケープ|説明 / 注釈|h |1|>|位置指定子|| |1-1||\b|ワードの境界(\w文字と\W文字の間)。&br;例えば「\bVB\b」で単語としての「VB」となる。&br;規定では日本語と英語の境界は「\b」に含まれない。&br;従って、「\bVB\b」という正規表現で、&br;「これは、VBです」という文字列中のVBを検索できない。&br;ただし、これについては、ECMAScriptオプションで動作を変更できる。&br;角括弧の中にある場合、置換パターンの場合は、下記、3-2を参照。| |1-2||\B|\b以外| |1-3||\A|MultiLineオプションを無視した文字列の先頭| |1-4||\z|MultiLineオプションを無視した文字列の末尾| |1-5||\Z|MultiLineオプションを無視した文字列の末尾(または文字列の末尾の「\n」の前) | |1-6||\G|前回の一致が終了した位置で一致する必要があることを指定する。| |2|>|メタ文字のエスケープ|単純に、前に¥記号を付与する。| |2-1||\.|.| |2-2||\^|^| |2-3||\$|$| |2-4||\*|*| |2-5||\+|+| |2-6||\?|?| |2-7||\[|[| |2-8||\]|]| |2-9||\(|(| |2-10||\|||| |2-11||\)|)| |2-12||\{|{| |2-13||\}|}| |2-14||\\|\| |3|>|制御文字|各種 制御文字を正規表現中の文字列で表す場合。| |3-1||\a|ベル(アラーム)の\u0007| |3-2||\b|角括弧の中にある場合、置換パターンの場合は、\u0008| |3-3||\t|タブの\u0009| |3-4||\r|キャリッジ リターンの\u000D| |3-5||\v|垂直タブの\u000B| |3-6||\f|フォーム フィードの\u000C| |3-7||\n|改行文字の\u000A| |3-8||\e|エスケープ文字の\u001B| |3-9||\cC|ASCII 制御文字 と一致(\cC は Ctrl + C)&br;http://ja.wikipedia.org/wiki/ASCII#ASCII.E5.88.B6.E5.BE.A1.E6.96.87.E5.AD.97| |4|>|コードポイント|各種 コードポイントを正規表現中の文字列で表す場合。| |4-1||\040|8進数(3桁まで)で表されるASCII文字と一致| |4-2||\x20|16進数(2桁)で表されるASCII文字と一致| |4-3||\u0020|16進数(4桁)で表されるUnicode文字と一致| **角括弧による文字グループ [#ue25e11a] 角括弧を使用した文字グループの定義には次のようなものがある。 ※ 下記の、Chn(Ch1、Ch2、Ch3、Ch4など)は文字を表す。~ xx_ChGroup(Base_ChGroup、Excluded_ChGroup)は文字グループを表す。 ***文字の連結 [#y7cc7c39] [Ch1Ch2] ***文字範囲(範囲指定) [#j38880b9] [Ch1-Ch2] ***文字範囲の連結 [#x5cd6a73] [Ch1-Ch2Ch3-Ch4] ***文字グループ減算式 [#od0b2869] [Base_ChGroup-[Excluded_ChGroup]].etc ***文字グループと文字クラスの減算式 [#e7fca066] -[\p{xxxx}-[Excluded_ChGroup]] -[Base_ChGroup-[Ch1-Ch2\p{xxxx}]] -, etc. **丸括弧による構成体 [#b0b52452] 丸括弧を使用した -[[グループ化構成体>#n212cb79]] -[[代替構成体>#nd7141a1]] -[[その他の構成体>#dbe024f2]] について説明する。 ***グループ化構成体 [#n212cb79] -グループ化構成体は、正規表現の部分式を表す(=グループ化)。 -正規表現にマッチした箇所はキャプチャされ、~ キャプチャ文字列として、プログラム中で利用できる。 --[[前後方参照>#s8e591e9]] --[[文字列置換>#r4700117]] -このグループ化構成体によるグループ化よって、~ 正規表現にマッチした箇所を部分的にキャプチャすることもできる。 -以下の表は、 --グループ化構成体の一覧で、表中の「expression」は、正規表現の部分式を意味する。 --「expression」中の&color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 |項番|区分|グループ化構成|>|説明|h ||||正規表現の例|マッチする部分文字列|h ||||>|キャプチャ文字列|h |1|>|>|>|グループ化| |1-1||(expression)|>|グループ化する箇所(丸括弧内をキャプチャする)。| |~|~|~|"大森(一郎|二郎) "|大森一郎または 大森二郎 にマッチ| |~|~|~|>|大森一郎、大森二郎以外に一郎、二郎が追加でキャプチャされる。| |1-2||(?:expression)|>|グループ化する箇所(丸括弧内をキャプチャしない)。| |~|~|~|"大森(?:一郎|二郎) "|大森一郎または 大森二郎 にマッチ| |~|~|~|>|大森一郎、大森二郎がキャプチャされ、一郎、二郎はキャプチャされない| |1-3||(?<name>expression)&br;※ < >は’でも良い。|>|グループ化する箇所(名前を付けて丸括弧内をキャプチャする)。| |~|~|~|"大森(?<name>一郎|二郎) "|大森一郎または 大森二郎 にマッチ| |~|~|~|>|大森一郎、大森二郎以外に一郎、二郎が追加でキャプチャされる。&br;※ このキャプチャ文字列は、グループ名(name)を使用して参照できる。| |1-4||(?imnsx-imnsx: expression)|>|指定した[[APIオプション>#q6a71c4d]]を部分式に適用(imnsxの部分)または無効(-imnsxの部分)にする。&br;正規表現の[[APIオプション>#q6a71c4d]]&br;https://msdn.microsoft.com/ja-jp/library/yd1hzczs.aspx| |1-5||(?<name1-name2>expression)|>|グループ定義を均等化する。| |1-6||(?>expression)|>|非バックトラッキング部分式。| |2|>|>|>|先読み・後読み(戻り読み)| |2-1||(?=expression)|>|直後にこのパターンが現れることを確認する。| |~|~|~|"\d+(?=%)"|後ろに「%」が続く数字の連続にマッチ| |~|~|~|>|「%」の部分はキャプチャされない。例えば100%で100がキャプチャされる。| |2-2||(?<=expression)|>|直前にこのパターンが現れることを確認する。| |~|~|~|"(?<=&color(,yellow){''\''};\)\d+"|「\」に続く数字の連続にマッチ。| |~|~|~|>|「\」の部分はキャプチャされない。例えば\100で100がキャプチャされる。| |2-3||(?!expression)|>|直後にこのパターンが現れないことを確認する。| |~|~|~|"\d+(?![\d%])"|後ろに「%」が続かない数字の連続にマッチ。| |~|~|~|>|「%」の部分はキャプチャされない。例えば100KSで100がキャプチャされる。| |2-4||(?<!expression)|>|直前にこのパターンが現れないことを確認する。| |~|~|~|"(?<![\d&color(,yellow){''\''};\])\d+"|「\」に続かない数字の連続にマッチ。| |~|~|~|>|「\」の部分はキャプチャされない。例えば$100で100がキャプチャされる。| -グループ番号~ キャプチャ文字列には、其々グループ番号が与えられる。 --正規表現にマッチした箇所全体のキャプチャ文字列は、グループ番号0となる。 --グループ化により、追加でキャプチャされるキャプチャ文字列のグループ番号には、~ グループの位置順(左から右)に1から始まる番号が与えられる。 --例えば ---"(ab)(cd)(ef)"という正規表現にマッチした場合、 <----------0----------> ( a b ) ( c d ) ( e f ) <--1--> <--2--> <--3--> ---各グループのキャプチャ文字列に割り当てられる番号は次のようになる。 入力 : xxxabcdefxxx ・グループ0 : abcdef ・グループ1 : ad ・グループ2 : cd ・グループ3 : ef --入れ子にグループ化された場合、~ グループのキャプチャ文字列に割り当てられる番号は、~ 外側から内側に順に1から始まる番号が与えられる。 --例えば ---"(a(b(c)(d)(e(f))))"という正規表現にマッチした場合、 <----------------0----------------> ( a ( b ( c ) ( d ) ( e ( f ) ) ) ) <-6-> <-3-> <-4-> <----5----> <-------------2-------------> <----------------1----------------> ---各グループのキャプチャ文字列に割り当てられる番号は次のようになる。 入力 : xxxabcdefxxx ・グループ0 : abcdef ・グループ1 : abcdef ・グループ2 : bcdef ・グループ3 : c ・グループ4 : d ・グループ5 : ef ・グループ5 : f --なお、グループ番号は、グループ名の付与の影響を受けない。 ***代替構成体 [#nd7141a1] -代替構成体は、選択、条件分岐を表す。 -「expression」中の&color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 |項番|区分|代替構成体|>|説明|h ||||正規表現の例|マッチする部分文字列|h ||||>|キャプチャ文字列|h |1||(?(expression1)expression2)|>|expression1に一致した場合、そこからexpression2で検索| |~|~|~|"(?(^大森).*郎(&color(,yellow){''\''};\r?&color(,yellow){''\''};\n|$))"|大森一郎、大森二郎、大森三郎、などの行| |~|~|~|>|先頭が「大森」の場合、末尾が「xxx郎」の行があれば、その行がキャプチャされる。| |2||(?(expression)yes_exp|no_exp)|>|expressionに一致した場合、そこからyes_expで検索&br;一致しなかった場合、そこからno_expで検索| |~|~|~|"(?(^大森).*郎(&color(,yellow){''\''};\r?&color(,yellow){''\''};\n|$)|^品川.*郎(&color(,yellow){''\''};\r?&color(,yellow){''\''};\n|$))"|大森一郎、大森二郎、大森三郎、品川一郎、品川二郎、品川三郎、などの行| |~|~|~|>|先頭が「大森」の場合、末尾が「xxx郎」の行があれば、その行がキャプチャされる。&br;また、先頭が「大森」でない場合、先頭「品川」 ~末尾「xxx郎」の行がキャプチャされる。| |3||(?(name)yes_exp|no_exp)|>|割愛| ***その他の構成体 [#dbe024f2] その他の構成体は、正規表現を変更する部分式([[APIオプション>#q6a71c4d]]、コメントなど)を表す。 |項番|その他の構成体|説明|h |1|(? imnsx - imnsx )|パターンの途中で[[APIオプション>#q6a71c4d]]を適用(imnsxの部分)または無効(-imnsxの部分)にする。 | |2|(?# )|正規表現に挿入するインライン コメント。コメントは、最初の右かっこ文字で終了する。| |3|# [行末まで]|X モード コメント。コメントは行末まで継続する。&br;このコメントを認識させるには、以下の何れかの[[APIオプション>#q6a71c4d]]を有効にする。&br;・xオプション&br;・IgnorePatternWhitespaceオプション| **キャプチャの利用 [#bff3e596] -キャプチャ文字列は --[[前後方参照>#s8e591e9]] --[[文字列置換>#r4700117]] >で参照(利用)できる。 -ここでは、 --[[前後方参照>#s8e591e9]] / [[文字列置換>#r4700117]]の使用方法と、 --キャプチャ文字列の参照方法に >ついて説明する。 ***前後方参照 [#s8e591e9] 前後方参照は、2つ連続する文字(文字グループ)のパターンを検索する場合などに使用する。 -前後方参照には、以下の2つの前後方参照構成体を使用する方法がある。 --グループ番号:\number ---「\1」から「\9」までの式は常に前後方参照を表し、8進のASCIIコードにはならない。 ---「\11」以降の複数桁の式は、その番号に対応する前後方参照がある場合には、前後方参照と見なされる。 ---それ以外の場合は、8進のASCIIコードと解釈される。~ ただし、先頭の桁が8または9の場合を除く。~ その場合はリテラルの"8"および"9"として扱われる。 --グループ名:\k<name> -正規表現の中に、未定義のグループ番号への前後方参照が含まれる場合は、~ 解析エラーと見なされる。曖昧さが問題となる場合は、名前を使用して前後方参照する。 -下記は、 --2つ連続する文字(文字クループ)のパターンを検索する「前後方参照」を使用した正規表現の例である。 --「expression」中の&color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 --「前後方参照」を使用した正規表現の例 ---2つ連続する文字のパターンを検索する ||グループ番号を使用|グループ名を使用|h |正規表現 前後方参照|"(&color(,yellow){''\''};\S)&color(,yellow){''\''};\1"|"(?<ch>&color(,yellow){''\''};\S)&color(,yellow){''\''};\k<ch>"| ---2つ連続する文字グループのパターンを検索する ||グループ番号を使用|グループ名を使用|h |正規表現 前後方参照|"&color(,yellow){''\''};\b(&color(,yellow){''\''};\S+)&color(,yellow){''\''};\s+&color(,yellow){''\''};\1&color(,yellow){''\''};\b"|"&color(,yellow){''\''};\b(?<str>&color(,yellow){''\''};\S+)&color(,yellow){''\''};\s+&color(,yellow){''\''};\k<str>&color(,yellow){''\''};\b"| ***文字列置換 [#r4700117] -文字列置換は、 --正規表現にマッチした箇所のキャプチャ文字列を使用して、~ 文字列の置換(付加、削除、書式変更など)を行うことができる。 --[[API>#q6a71c4d]]を使用して、正規表現、置換パターン、[[APIオプション>#q6a71c4d]]を指定して、~ 付加、削除、書式変更などの処理を実行できる。 -置換パターンに指定する置換構成体には、次のものがある。 |項番|置換構成体|説明|h |1|$number|グループ番号と一致した部分文字列| |2|${name}|グループ名(name)と一致した最後の部分文字列| |3|$&|一致したパターン全体の文字列| |4|$+|キャプチャされた最後の文字列| |5|$_|入力文字列全体| |6|$`|一致した場所より前にある入力文字列| |7|$'|一致した場所より後にある入力文字列| |8|$$|単一の "$" リテラル(エスケープ)| -次に、正規表現による文字列置換の例を示す。 --付加 ---HTML中のURLにリンクを付ける。~ ※ 正規表現にマッチした箇所全体のキャプチャ文字列は、置換構造体「$0」でも「$&」でも参照できる。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープと、~ C#に於ける「"」のエスケープ(VBの場合は「"」を使用)。 ||$0版|$&版|h |正規表現|>|"s?https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+"| |置換パターン|"<a href=&color(,yellow){''\''};"$0&color(,yellow){''\''};">$0</a>"|"<a href=&color(,yellow){''\''};"$&&color(,yellow){''\''};">$&</a>"| ---文書中の行頭に引用記号を挿入する。~ ※ 正規表現に位置指定子(アトミック ゼロ幅アサーション)を単独で使用した場合もキャプチャ → 置換ができる。 ||文字列|h |正規表現|"^"| |置換パターン|"> "| --削除 ---文書中の行末の空白文字を削除する。~ ※ 削除する場合、置換パターンに空文字列を指定する。~ ※ 実行時、Multilineオプションを設定する必要がある。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 ||文字列|h |正規表現|"[&color(,yellow){''\''};\t]+(?=&color(,yellow){''\''};\r?&color(,yellow){''\''};\n|$)"| |置換パターン|"" (空文字列)| ---無効な文字を削除する。~ ※ 削除する場合、置換パターンに空文字列を指定する。~ ※ @、- (ハイフン)、および . (ピリオド) 以外のすべての非英数文字を取り除いた文字列を返す。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 ||文字列|h |正規表現|"[^&color(,yellow){''\''};\w&color(,yellow){''\''};\.@-]"| |置換パターン|"" (空文字列)| ---文書中の連続する同じ行を削除する。~ ※ 上記は、[[前後方参照>#s8e591e9]]を併用している。~ ※ 実行時、Multilineオプションを設定する必要がある。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 ||グループ番号を使用|グループ名を使用|h |正規表現|"^(.*)(&color(,yellow){''\''};\r?&color(,yellow){''\''};\n&color(,yellow){''\''};\1)+$"|"^(?<line>.*)(&color(,yellow){''\''};\r?&color(,yellow){''\''};\n&color(,yellow){''\''};\k<line>)+$"| |置換パターン|"$1"|"${line}"| -書式変更 --日付のフォーマットを変更する1~ ※文章中から検索、変換する場合は、前後に「\b」を付与する必要がある。~ また、日本語文章中の場合は、実行時、ECMAScriptオプションを設定する必要がある。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 ||グループ名を使用|h |正規表現|"(?<year>&color(,yellow){''\''};\d{2,4})/(?<month>&color(,yellow){''\''};\d{1,2})/(?<day>&color(,yellow){''\''};\d{1,2})"| |置換パターン|"${year}年${month}月${day}日"| --日付のフォーマットを変更する2~ ※ 文章中から検索、変換する場合は、前後に「\b」を付与する必要がある。~ また、日本語文章中の場合は、実行時、ECMAScriptオプションを設定する必要がある。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 ||グループ名を使用|h |正規表現|"(?<month>&color(,yellow){''\''};\d{1,2})/(?<day>&color(,yellow){''\''};\d{1,2})/(?<year>&color(,yellow){''\''};\d{2,4})"| |置換パターン|"${day}-${month}-${year}"| --その他、MatchEvaluatorデリゲートを使用して置換(変換)するという方法もあるが、~ これについては、「[[API>#q6a71c4d]]」で説明する。 **最長 / 最短マッチ [#c940097d] デフォルトでは「[[最長マッチ>#y2259122]]」となるため、必要に応じて「[[最短マッチ>#vec3cd85]]」を使用する。 ***最長マッチ [#y2259122] -「最長マッチ」とは、検索される文字列が最長になるように処理することである。 -例えば、カギかっこ(「」)で囲まれた文字列を検索する場合、 --次のように正規表現を表記した場合に、 "「.*」" --カギかっこが複数あった場合、問題が起こる。 ---例えば、入力文字列に、以下のように入力されているならば、 "・・・「あ」、「い」、「う」・・・" ---検索される部分文字列は、以下の1つだけになる。 "「あ」、「い」、「う」" --これを、以下の3つの文字列が別々に検索されるようにするには、[[最短マッチ>#vec3cd85]]を使用する。 "「あ」"、"「い」"、"「う」" ***最短マッチ [#vec3cd85] -「最短マッチ」とは、検索される文字列が最短になるように処理することである。 -「最短マッチ」を「最短マッチ」にする場合、以下のように、書き換える必要がある 。 "「.*」" → "「.*?」" -ただし、上記のような例であれば、~ 「最短マッチ」を使用しなくても、"「[^」]*」"と書けばほぼ同じことができる。 *パターン マッチの例 [#q69548a9] 正規表現を使用したパターン マッチの例を示す。 **メールアドレスを検索する [#a45bedd2] ※ IgnoreCase(大文字と小文字を区別しない)オプションを設定する必要がある。~ ※ 文章中から検索する場合は、前後に「\b」を付与する必要がある。~ また、日本語文章中の場合は、実行時、ECMAScriptオプションを設定する必要がある。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 |||h |正規表現|"[A-Z0-9._%+-]+@[A-Z0-9.-]+&color(,yellow){''\''};\.[A-Z]{2,4}"| |~|"([&color(,yellow){''\''};\w-&color(,yellow){''\''};\.]+)@((&color(,yellow){''\''};\[[0-9]{1,3}&color(,yellow){''\''};\.[0-9]{1,3}&color(,yellow){''\''};\.[0-9]{1,3}&color(,yellow){''\''};\.)|(([\\w-]+&color(,yellow){''\''};\.)+))([A-Z]{2,4}|[0-9]{1,3})(&color(,yellow){''\''};\]?)"| **HTML内のリンク先を検索する [#y327d7db] ※ 上記は、前方参照、最小マッチを併用している。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープと、~ C#に於ける「"」のエスケープ(VBの場合は「"」を使用)。 |||h |正規表現|"href&color(,yellow){''\''};\s*=&color(,yellow){''\''};\s*(?:(?<quot>[&color(,yellow){''\''};"'])(?<url>.*?)&color(,yellow){''\''};\k<quot>)"&br;→「クォーテーション無し」を考慮していない例。| |~|"href&color(,yellow){''\''};\s*=&color(,yellow){''\''};\s*(?:&color(,yellow){''\''};"(?<1>[^&color(,yellow){''\''};"]*)&color(,yellow){''\''};"|(?<1>&color(,yellow){''\''};\S+))"&br;→「シングル クォーテーション」を考慮していない例。| **HTML内の見出し、<H1>~<H6>タグを検索する [#ecb2360a] ※ 上記は、前方参照、最小マッチを併用している。~ ※ 実行時、Singleline(「.」に、\nを含める)オプションを設定する必要がある。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 |||h |正規表現|"<(h[1-6])&color(,yellow){''\''};\b[^>]*>(.*?)</&color(,yellow){''\''};\1>"| **HTML内のリンク、<a>タグから情報を抽出する [#q6f9bc67] ※ 上記は、前方参照、最小マッチを併用している。また、url、textなどの部分キャプチャを行なっている。~ ※ 実行時、IgnoreCase(大 / 小文字を区別しない)、Singleline(「.」に、\nを含める)オプションを設定する必要がある。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープと、~ C#に於ける「"」のエスケープ(VBの場合は「"」を使用)。 |||h |正規表現|"<a&color(,yellow){''\''};\s+[^>]*href&color(,yellow){''\''};\s*=&color(,yellow){''\''};\s*(?:(?<quot>[&color(,yellow){''\''};"'])(?<url>.*?)&color(,yellow){''\''};\k<quot>|(?<url>[^&color(,yellow){''\''};\s>]+))[^>]*>(?<text>.*?)</a>"| **URL文字列から情報を抽出する [#k4c43c8e] ※ 最小マッチを使用している。また、プロトコル、ポート番号などの部分キャプチャを行なっている。~ ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 |||h |正規表現|"^(?<proto>&color(,yellow){''\''};\w+)://[^/]+?(?<port>:&color(,yellow){''\''};\d+)?/"| *利用するAPI、オプション [#q6a71c4d] 正規表現の処理に利用するAPIと、そのオプションについて説明する。 **API [#u8ae2f7d] 正規表現にて中心的役割を担うクラスに[[Regexクラス>#l183e4fb]]と[[Matchクラス>#ab47d056]]がある。 ***Regexクラス [#l183e4fb] Regexクラスは、正規表現パターンを格納し、パターン マッチングを実行するメソッドを備えたクラスである。~ このオブジェクトからキャプチャ文字列の値を取り出して、引き続き、「手続き型の処理」を実装できる。 -以下に、Regexクラスの主要なプロパティ / メソッドを一覧する。 |項番|区分|名前|説明|h |1|>|>|プロパティ| |1-1||Options|Regexコンストラクタに渡されたオプション(5.2節を参照)| |2|>|>|メソッド| |2-1||IsMatch|正規表現と一致する対象が入力文字列内で見つかったかどうかを示す。&br;主に、入力チェックを実装する場合に利用し、入力チェックでは、&br;正規表現の先頭と末尾に「 ^ 」と「 $ 」を付与して中間からのマッチを拒否すると良い。| |2-2||Match|入力文字内で正規表現と一致する対象を1つ検索し、結果を[[Matchオブジェクト>#ab47d056]]として返す。&br;取得した[[Matchオブジェクト>#ab47d056]]のNextMatchメソッド(後述)が呼び出された場合、次の結果を[[Matchオブジェクト>#ab47d056]]として返す。| |2-3||Matches|入力文字列内で正規表現と一致する対象をすべて検索し、&br;結果の複数の[[Matchオブジェクト>#ab47d056]](見つかった対象をすべて返す)をMatchCollectionとして返す。| |2-4||Replace|第一引数の正規表現パターンに一致する文字列を、第二引数の置換パターンで置換する。&br;第二引数にはMatchEvaluatorデリゲートを使用して置換(変換)することもできる(後述)。| |2-5||Split|入力文字列を、正規表現によって定義されている位置で配列に分割する。| -オブジェクト階層は次のようになっている。 --Matchesメソッドで取得できるMatchCollectionオブジェクト --Matchメソッドで取得できる[[Matchオブジェクト>#ab47d056]] オブジェクト名 : 下位オブジェクトの取得方法 : キャプチャ文字列の詳細データ MatchCollectionオブジェクト : インデクサ(番号) ┗ Matchオブジェクト : Groupsプロパティ ┗ GroupsCollectionオブジェクト : インデクサ(番号、名称) ┗ Groupsオブジェクト : Capturesプロパティ ┗ CaptureCollectionオブジェクト : インデクサ(番号) ┗ Captureオブジェクト : 各種プロパティ ┣ Value(string) : キャプチャ文字列の値 ┣ Length(int) : キャプチャ文字列の長文字列 ┗ Index(int) : 入力文字列を基にした位置(インデックス) -其々のオブジェクトの説明 |項番|オブジェクト名|説明|h |1|[[Matchオブジェクト>#ab47d056]]|正規表現により「検索された1つの文字列」と対応する結果を格納。| |2|Groupsオブジェクト|上記「検索文字列」のキャプチャ、クループ化による追加キャプチャの情報を格納。| |3|Captureオブジェクト|キャプチャ文字列の詳細データを格納| -1つのグループが複数の文字列をキャプチャする例~ 正規表現によっては、1つのグループが複数の文字列をキャプチャすることがある。~ このような正規表現の例を以下、説明する。 --正規表現の例 |||h |正規表現|"(123)(&color(,yellow){''\''};\d)+(789)"| |入力文字列|"123456789-123456789"| ※ &color(,yellow){''ハイライトの「\」''};は、リテラル中の「\」のエスケープ。 --上記を実行した結果、~ 以下のオブジェクトが返される。 ---[[Matchオブジェクト>#ab47d056]](2つ)~ ・前の"123456789"にマッチ~ ・後ろの"123456789"にマッチ ---Groupsオブジェクト(4つ)~ ・全体(123456789)のキャプチャ~ ・グループ 1(123)のキャプチャ~ ・グループ 2("\d"=4)のキャプチャ~ ・グループ 3("\d"=5)のキャプチャ~ ・グループ 4("\d"=6)のキャプチャ~ ・グループ 5(789)のキャプチャ -MatchEvaluatorデリゲートを使用して置換(変換)する例 --また、Regex.Replace ( ) メソッドの特殊な使い方に、~ MatchEvaluatorデリゲートを使用した置換(変換)方法がある。 --これを使用すると、非手続の「置換パターン」を使用した置換(変換)ではなく、~ 手続き型言語(C#、VB)を使用した置換(変換)が可能になる。 public class Test_Regex { // 正規表現を使用して置換(変換)するメソッド public string Regex_Replace(string yyyymmdd) { // 日付(yyyy/mm/dd形式)を正規表現を用いて1日増やす return Regex.Replace(yyyymmdd, @"(?<year>\d{4})/(?<month>\d{2})/(?<day>\d{2})", new MatchEvaluator(this.IncrementDay)); } // MatchEvaluatorデリゲートメソッド private string IncrementDay(Match m) { // 日付ワーク DateTime dt; // 日付(yyyy/mm/dd形式)をDateTime型に変換 if (DateTime.TryParse(m.Value, out dt)) { // DateTimeクラスを使用して1日増やし、 // 日付(yyyy/mm/dd形式)に戻す。 return dt.AddDays(1).ToShortDateString(); } else { // 変換できなかった場合、何もしないで戻す。 return m.Value; } } } ***Matchクラス [#ab47d056] Matchクラスは、[[Regexクラス>#l183e4fb]]で実行されたパターン マッチングの結果を格納するクラスである。 -以下に、Matchクラスのプロパティ / メソッドを一覧する。 |項番|区分|名前|説明|h |1|>|>|プロパティ| |1-1||Success|一致した対象が見つかったかどうかを示すbool値を取得する。&br;例えば、量指定子「 * 」を指定したグループ構成体は、見つからないことが有り得る。| |1-2||Groups|正規表現による「検索文字列」の&br;・キャプチャ(グループ0)、&br;・グループ化による追加キャプチャ(グループ1 ~ )&br;の情報を格納。| |1-3||Captures|グループ0のキャプチャ| |1-4||Value|グループ0のキャプチャ文字列の値| |1-5||Length|グループ0のキャプチャ文字列の文字列長| |1-6||Index|グループ0の入力文字列を基にした位置(インデックス)| |2|>|>|メソッド| |2-1||NextMatch|次の結果をMatchオブジェクトとして返す。| |2-2||Result|指定された置換パターンを返す(結果毎に置換パターンを変更できる)。| **オプション [#ff9e081c] 以下、[[Regexクラス>#l183e4fb]]のオプションについて説明する。~ これによって一部、動作(処理結果)が変更される。 |項番|RegexOptions列挙体のメンバ|説明|h |1|None|オプションが何も設定されないことを指定する。| |2|ECMAScript|ECMAScript準拠の動作とする。一部のメタ文字の意味が変更される。&br;・ECMAScript とします。 標準一致の動作&br; http://msdn.microsoft.com/ja-jp/library/04ses44d.aspx| |3|Singleline|ワイルドカードである.(ピリオド)の意味を、「\n」を含めたすべての文字の意味に変更する。| |4|Multiline|「^」と「$」の意味を&br;・「^」:「文字列の先頭」 → 「行の先頭」&br;・「$」:「文字列の末尾」 → 「行の末尾」&br;に変更する。&br;「^」と「$」の代わりに「\A」と「\Z」を使用すると、&br;Multilineの影響を受けずに「文字列の先頭」、「文字列の末尾」を指定できる 。| |5|IgnoreCase|大文字と小文字を区別しない。| |6|CultureInvariant|言語(カルチャ)の違いを無視する。&br;・RegularExpressions 名前空間でのカルチャを認識しない操作の実行&br; http://msdn.microsoft.com/ja-jp/library/z0sbec17.aspx| |7|RightToLeft|検索が左から右(→)ではなく右から左(←)に行われるように指定する。| |8|Compiled|正規表現をコンパイルして実行速度を上げる。ただし、起動時間は長くなる。&br;・正規表現におけるコンパイルと再利用&br; http://msdn.microsoft.com/ja-jp/library/8zbs0h2f.aspx| |9|ExplicitCapture|明示的に名前を指定されたグループだけが有効なキャプチャであることを指定する。| |10|IgnorePatternWhitespace|・正規表現のパターン内にコメント文を記述するには?[C#、VB] - @IT&br; http://www.atmarkit.co.jp/fdotnet/dotnettips/582regexcomment/regexcomment.html| *まとめ [#zc5b599c] **正規表現により解決できる点 [#y230cd77] 正規表現を使用すると、高度な、 -入力チェック -全文検索 -置換(付加、削除、書式変更) -文字列分割 などの処理を、高い生産性で実装することができる。 **正規表現により解決できない点 [#ad988f75] ただし、以下の点は、正規表現により解決できない。 ***妥当性の検証が困難 [#o3cdbc00] -記述(処理の実装ステップ数)は、短かくなるが、 --正規表現を習得する必要がある。 --アサインする技術者には正規表現の知識が必要になる。 -「非手続き言語」の特徴として、開発したステップ数に対するテスト ケースが多い。 --それを検証するテスト工数の削減はできないし、 --テストケースが網羅的であるかどうか、カバレージを指標に利用できない。 ***表現できないケースがある [#a78f7cff] -「手続き言語」で実装しないと表現できないケースもある。~ 例えば、メール フォーマット チェックなどを例に挙げて説明すると、 --RFCに準拠したメール アドレスだけ許可するのか? --携帯メールなどに見られるRFC非準拠のメール アドレスも許可するのか? --また、電子メールの配送先IPアドレスの直接指定を許可するのか?など。 ***利便性と汎用的の両立は依然として困難 [#a9d67bb4] -正規表現は、 --入力チェック処理や、 --置換(書式変更)などの >共通処理を、比較的容易に開発できる。 -しかし、利便性と汎用的を両立するAPI仕様を検討することは変わらず難しい 。~ このため、強度を上げるなら、汎用性を犠牲にする以外に方法が無い。 *参考 [#s88876ee] -.NET Framework の正規表現~ http://msdn.microsoft.com/ja-jp/library/hs600312.aspx -正規表現の基本 - .NET Tips (VB.NET,C#...)~ http://dobon.net/vb/dotnet/string/regex.html -正規表現 (System.Text.RegularExpressions)~ Programming/.NET Framework - 総武ソフトウェア推進所~ http://smdn.jp/programming/netfx/regex/ -サルにもわかる正規表現入門~ http://www.mnet.ne.jp/~nakama/ -Regular-Expressions.info~ Regex Tutorial, Examples and Reference - Regexp Patterns~ http://www.regular-expressions.info/index.html