正規表現講座 .Net Framework版(Part2)

こんにちは、以前「正規表現講座 .Net Framework版」でご紹介しましたブログの続きを書きましたのでご紹介します。
一致文字
文字エスケープ
「正規表現の基本」でも書きましたが、一部の記号には特殊な意味があり、その記号そのものにはマッチできません。これを解消するのが「\」記号によるエスケープです。
「\*」は、「*」にマッチする正規表現です。
> ‘*’ -match ‘*’(エラーが発生する) > ‘*’ -match ‘\*’ True |
同様に「\.」や「\(」「\[」といった正規表現があります。
また、記号以外が続くことで特殊な意味になるものもあります。
パターン | 説明 | 例 |
\t | タブと一致します | > (9 -as [Char]) -match ‘\t’True > “`t” -match ‘\t’ True |
\r | CR(ASCIIコード13、Windows改行CRLFの前半)と一致します | > (13 -as [Char]) -match ‘\r’True > “`r” -match ‘\r’ True |
\n | LFと一致します(既出) | > (10 -as [Char]) -match ‘\n’True > “`n” -match ‘\n’ True |
\x00 | 16進数表現で文字を指定(00は2桁の16進数) | > “`n” -match ‘\x0a’True |
\u0000 | 16進数表現でUnicode文字を指定(0000は4桁の16進数) | > “`n” -match ‘\u000a’True |
他にもありますが、あまり使われません。
文字クラス
「正規表現の基本」で「文字グループ」として書いたものです。
個別指定、範囲指定の他に、除外指定と既定のものがあります。(既定のものは後述します)
「[^abc]」は、「a」「b」「c」以外の文字にマッチします。大括弧の外の「^」は行頭にマッチしますが、大括弧内先頭の「^」は、否定表現となります。
「[^0-9]」は、「0」~「9」以外の文字にマッチします。
> ‘a’ -match ‘[^abc]’False > ‘0’ -match ‘[^abc]’ True > ‘a’ -match ‘[^0-9]’ True |
なお、先頭でない場合は否定表現となりません。「[1^]」は、「1」「^」にマッチします。
例題
・「.net framework」に一致し「xnet framework」に一致しない正規表現は?
・先頭のタブに一致する正規表現は?
・全角ひらがなを含まない文字列に一致する正規表現は?
文字クラス詳細
既定の文字クラス
既定の文字クラスは、文字エスケープに似ていますが、複数の文字にマッチするところが違いです。
既定の文字クラスを使う必要はありませんが、可読性のために使うことが多いです。
パターン | 説明 | 例 |
\s | [ \n\r\t]です。半角スペース、CR、LF、タブ(厳密には違うがだいたいこの通り。以下同じ) LFを含むことに注意。 |
> ‘ ‘ -match ‘\s’True > ‘a’ -match ‘\s’ False |
\S | [^\s]、すなわち[^ \n\r\t]です | > ‘ ‘ -match ‘\S’False > ‘a’ -match ‘\S’ True |
\d | [0-9]です。(厳密には違うがだいたいこの通り) | > ‘1’ -match ‘\d’True > ‘a’ -match ‘\d’ False > ‘ ‘ -match ‘\d’ False |
\D | [^\d]、すなわち[^0-9]\d以外なので、\sも含む | > ‘1’ -match ‘\D’False > ‘a’ -match ‘\D’ True > ‘ ‘ -match ‘\D’ True |
\w | [a-zA-Z_0-9]です。小文字・大文字・アンダースコア・数字(厳密には違うがだいたいこの通り) | > ‘1’ -match ‘\w’True > ‘a’ -match ‘\w’ True > ‘ ‘ -match ‘\w’ False |
\W | [^\w]、すなわち[^a-zA-Z_0-9]です。\sを含むことに注意。 | > ‘1’ -match ‘\W’False > ‘a’ -match ‘\W’ False > ‘ ‘ -match ‘\W’ True |
文字クラス詳細
文字クラスの範囲指定は、複数を含めることが可能です。
「[0-9a-z]」は、数字か小文字にマッチする正規表現です。
> ‘d’ -match ‘[0-9a-z]’True > ‘2’ -match ‘[0-9a-z]’ True |
あまり使われませんが、以下のような文字クラスも存在します。
パターン | 説明 | 例 |
\p{ name } | nameで指定された名前付きブロックまたはUnicode一般カテゴリ内の1文字と一致します。詳細はMSDNを参照願います。 | > ‘あ’ -match ‘\p{IsHiragana}’True > ‘a’ -match ‘\p{IsHiragana}’ False |
\P{ name } | [^\P{ name }]です。\sを含むことに注意。 | > ‘あ’ -match ‘\P{IsHiragana}’False > ‘a’ -match ‘\P{IsHiragana}’ True |
[ base – [ exclude ] ] | 文字クラスの減算です。Baseのクラスから、excludeのクラスを排除します。 | > ‘5’ -match ‘[\d-[345]]’False > ‘2’ -match ‘[\d-[345]]’ True |
例題
・16進数文字にのみマッチする正規表現は?
・カタカナにマッチする正規表現は?(\pを使って)
・数字・アルファベット(大文字・小文字)にマッチする正規表現は?
文字列
グループ、前方参照、代替構成
「正規表現の基本」で書いたグループ化関連です。
グループは、後述の置換や、今回説明する前方参照、また、検索結果を取得する際に効果があります。
通常のグループ化と前方参照
グループ化したものは、「\1」といった形で参照できます。
> ‘aa aa’ -match ‘(aa|bb) \1’True > ‘bb bb’ -match ‘(aa|bb) \1’ True > ‘aa bb’ -match ‘(aa|bb) \1’ False |
上記の例では、「\1」はグループ化の1番目を参照しています。
「aa aa」とのマッチでは、「(aa|bb)」部分は「aa」とマッチするため、「\1」は「aa」とみなされ、マッチすることになります。
「bb bb」も同様です。
「aa bb」は、「(aa|bb)」部分は「aa」とマッチし全体では「aa aa」とマッチを見ることになるため、Falseになります。
「\1」といった表記は「\9」までは安全に使えますが、それ以降はリテラルとの混同があるため注意が必要です。
番号は「(」左括弧の出現順番と思えば問題ありません。
通常のグループ化と検索結果
Powershellでは、マッチ結果が自動変数「$Matches」に格納されます。
Powershellの場合は、これを参照することで検索結果を確認できます。
> ‘aa aa’ -match ‘(aa|bb) \1’True > $MatchesName Value —- —– 1 aa 0 aa aa > ‘aa bb’ -match ‘(aa|bb) \1’ Name Value |
$MatchesのName=1のものが「\1」相当、Name=0のものはマッチした全体です。
-match演算がFalseの場合、$Matchesは更新されないことに注意が必要です。
名前付きグループ化と前方参照、検索結果
グループには名前が付けられます。
番号で前方参照する場合、簡単なものは良いですが、複雑な場合は名前を付けることがおすすめです。
> ‘aa bb’ -match ‘(?<first>aa|bb) \k<first>’False > ‘aa aa’ -match ‘(?<first>aa|bb) \k<first>’ True > $MatchesName Value —- —– first aa 0 aa aa |
$MatchesのNameにもグループ化の名前が適用されます。
キャプチャしないグループ
置換や前方参照、検索結果に利用しないグループは、キャプチャしないことが可能です。
> ‘aa’ -match ‘(?:aa|bb)’True > $MatchesName Value —- —– 0 aa |
「(?:」でグループ化することで、キャプチャしないため、$MatchesにはName=0、全体しかありません。
例題
・「わんわん」「にゃんにゃん」「メーメー」といった同一文字列が繰り返すパターンにマッチする正規表現は?
量指定子詳細
「正規表現の基本」でも量指定子について少しふれました。(「*」と「?」のみ)
ここでは、.Netの持つ豊富な量指定子を紹介します。
*
前述のように任意の個数にマッチする量指定子です。
さらに言うと、基本的に全ての量指定子は、最長一致です。
> ‘aaa’ -match ‘a*’True > $MatchesName Value —- —– 0 aaa |
任意個の「a」ということは、「aaa」とマッチした場合、「aaa」(3個)「aa」(2個)「a」(1個)「」(0個!)の4パターンでマッチすることになりますが、最長一致のため3個でマッチします。
?
前述のように0または1個にマッチする量指定子です。
これも最長一致のため、0と1個の両方にマッチできる場合、1個にマッチします。
+
1個以上にマッチする量指定子です。
「a+」は、「aa*」と等価です。
> ‘aaabbb’ -match ‘a+’True > ‘bbb’ -match ‘a+’ False |
1個以上のため、ゼロ個ではマッチしません。
{n}
n個にマッチする量指定子です。
以上でも以下でもいけません。
> ‘aaa’ -match ‘a{3}’True > ‘aa’ -match ‘a{3}’ False > ‘aaaa’ -match ‘a{3}’ True |
以上でもいけないのに、「aaaa」にマッチしました。
これは、4文字のうち前3文字にマッチしたためです。
前述のアンカーを使うと、以上でもマッチしないことが確認できます。
> ‘aaa’ -match ‘^a{3}$’True > ‘aa’ -match ‘^a{3}$’ False > ‘aaaa’ -match ‘^a{3}$’ False |
{n,}
n個以上にマッチする量指定子です。
> ‘aaa’ -match ‘a{3,}’True > ‘aa’ -match ‘a{3,}’ False > ‘aaaaa’ -match ‘a{3,}’ True > $MatchesName Value —- —– 0 aaaaa > ‘aaaaa’ -match ‘a{3}’ Name Value |
「aaaaa」に対する「a{3,}」のマッチ結果は「aaaaa」です。
「a{3}」のマッチ結果は「aaa」です。
{n,m}
n個以上m個以下にマッチする量指定子です。
> ‘aaaa’ -match ‘a{3,5}’True > ‘aa’ -match ‘a{3,5}’ False > ‘aaaaaa’ -match ‘a{3,5}’ True > $MatchesName Value —- —– 0 aaaaa |
量指定子の追加要素:?
量指定子の直後に「?」をつけると、最短一致になります。
> ‘aaa’ -match ‘a*?’True > $MatchesName Value —- —– 0 |
0個以上の最短一致のため、長さ0の文字列にマッチします。
> ‘aaa’ -match ‘a??’True > $MatchesName Value —- —– |
0個または1個の最短一致のため、これも長さ0の文字列。
> ‘aaa’ -match ‘a+?’True > $MatchesName Value —- —– 0 a |
1個以上の最短一致のため、「a」一文字。
> ‘aaa’ -match ‘a{3}?’True > $MatchesName Value —- —– 0 aaa |
3個の最短一致は、最長一致と同じです。
> ‘aaaa’ -match ‘a{3,}?’True > $MatchesName Value —- —– 0 aaa |
3個以上の最短一致は、3個です。
> ‘aaaa’ -match ‘a{3,5}?’True > $MatchesName Value —- —– 0 aaa |
3~5個の最短一致は、3個です。
一見3以上と同じようですが、アンカー等と組み合わせることで3以上と差があります。
> ‘aaaaa’ -match ‘^a{3,5}?$’True > ‘aaaaaa’ -match ‘^a{3,5}?$’ False |
例題
・メールアドレスのドメイン名部分をキャプチャする正規表現は?(キャプチャにはグループを使います。ドメイン名には、英数字と半角ハイフンが使えるものとします。有効なメールアドレスには「”aaa@bbb”<ccc@ois-yokohama.co.jp>」といったものもあります)
・市外局番を除いた電話番号を市内局番と回線番号4桁にキャプチャする正規表現は?