正規表現講座 .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’
False
> $Matches

Name                           Value
—-                           —–
1                              aa
0                              aa aa

$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}’
True
> $Matches

Name                           Value
—-                           —–
0                              aaa

「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桁にキャプチャする正規表現は?

前の記事

インターンシップのご案内

次の記事

2月3日は節分です