正規表現 RegExp

中級VBA

正規表現とは

 正規表現は様々なプログラミング言語で使用される文字列マッチング手法です。
VBAでは、VBScript.RegExpオブジェクトで使用することができます。

 具体的にはメタ文字と呼ばれる特殊に割り当てた文字や記号を組み合わせる事で、文字列マッチングのルールを定義して、それに適合する場所を特定して別の文字列に置き換えたり抜き出したりすることができます。

 正規表現自体は、汎用的な文字列マッチングの手法なので、他のプログラミング言語でも使えるため、利用価値が高いと言えるでしょう。

 ただ、覚える事も多く内容も複雑であるため、ここでは基本的な部分を解説します。

メタ文字 (正規表現で特別の意味を持つ文字)

「\d」 — 1個の半角数字(0-9)
「\w」 — 1個の文字(a-z A-Z 0-9 _)
「\s」 — 1個のスペース、タブ、改行

尚、それぞれ大文字にするとそれらの否定となります。
「\D」 — 1個の半角数字(0-9)以外
「\W」 — 1個の文字(a-z A-Z 0-9 _)以外
「\S」 — 1個のスペース、タブ、改行以外

メタ文字の反対語として、リテラル文字があります。リテラル文字はそのままの文字になります。

メタ文字をリテラル文字として使いたいときは\でエスケープします。

量指定子 (以上、以下など数を指定できる)

「.」 — 任意の1文字(改行以外)
「?」 — 0か1個  {0,1}
「+」 — 1個以上  {1,}
「*」 — 0個以上  {0,}

「{n}」 — n個
「{n,m}」 — n個以上、m個以下
「{n,}」 — n個以上

最小量指定子

量指定子はデフォルトでは最大でマッチするようになっています。
最小でマッチさせるには ? を付けます。
「*?」
「+?」
「??」
「{n, m}?」

“a”, “b”, “c” の検索例

  ”.+”  — 「”a”, “b”, “c”」がマッチ
  ”.+?” — 「”a”」「”b”」「”c”」がそれぞれマッチ
“a”, “b”, “c” というケースでは、?を付けないと全てが選択されてしまう。

文字クラス (検索文字の集合を表す[ ])

[abc] — a, b, c のどれか

 - (ハイフンの位置に注意!)

 [a-z] はa,b,c,…z のどれかとなり、a,-,zのうちのどれかとはなりません。
そのようにしたいときは、[-az]としてハイフンを真ん中から外します。

 ^(ハットにも注意!)

文字クラス内の [ 直後の ^ は否定を意味します。直後でなければリテラル文字になります。
(行の先頭を示すメタ文字とは意味が違う!)
 [^a]はa以外という意味になる。

アンカー

「^」 — 行の先頭
「$」 — 行の末尾
「\b」 — 単語の境界

グループ化の丸括弧() と選択子 |

(apple|orange) とすると、apple または orange が対象となります。

検索例

マッチさせたい文字列

03-1234-5678
090-1234-5678
03(1234)5678
0120-111-1111

1番目の見ヒットさせる
^\d{2}-\d{4}-\d{4}

 ^ を付けないと2番めもヒットしてしまいます。

2番目のみヒットさせる
\d{3}-\d{4}-\d{4}
1番目と2番目をヒットさせる
\d{2,3}-\d{4}-\d{4}

 最初の量指定子を2以上3以下に指定します。

1番目と3番目をヒットさせる
^\d{2}[-(]\d{4}[-)]\d{4}

文字クラスを使って-と()を指定します。

3番目と4番目をヒットさせる
^(\d{2}\(|\d{4}-)\d{3,4}[-)]\d{4}

一番目をヒットさせないように、グループ化の( ) を利用して差別化しています。
尚、グループ内で ( を使用しているので、\( とエスケープさせる必要があります。

ExcelVBAで正規表現が使えるオブジェクトRegExp

今度はExcelVBAで使用するRegExpオブジェクトについて解説します。

ざっくり言いますと、RegExpオブジェクトは、以下の3つの処理ができます。

  • Testメソッド (マッチングに成功するか)
  • Replaceメソッド (マッチしたものを指定した文字に置き換える)
  • Executeメソッド (マッチしたものをMatchesコレクションとして返す)

今回作った Excelシートとプログラムコードは以下の通りです。

Sub RegExpMacro1()
 
Dim reg As Object
Set reg = CreateObject("VBScript.RegExp")   'RegExpオブジェクト作成
 
Range(”B6”)=""
 
'正規表現
With reg
.Pattern = Range("B4")     'パターンをセット
.IgnoreCase = False     '大文字と小文字区別
.Global = True          '文字列全体を検索するか
End With
 
Range("G2") = reg.test(Range("B2"))     'testメソッド:成功すればTrueを返す
 
Range("B6") = reg.Replace(Range("B2"), CStr(Range("D4"))) 'Replace:マッチした文字を第2引数に置換
 
End Sub

簡単なので興味のある方は作ってみてください。
適当なシートの B2、B4、D4、G2に値を入れれば、結果がB6に出力されます。
ボタンは、上記のコードを割り当てればOKです。

RegExpオブジェクトの準備

では、上記のプログラムを見ていきましょう。
まずは、RegExpオブジェクトを作ります。

Dim reg As Object
Set reg = CreateObject("VBScript.RegExp")

参照設定をした場合の書き方

参照設定を設定している場合は以下のようになります。

Dim reg As New RegExp

 参照設定は、VBEの「オプション」「参照設定」で 「Microsoft VBScript Regular Expressions 5.5」(※1)にチェックを入れます。
※1:筆者の環境はExcel2019です。

プロパティをセット

次はプロパティをセットします。

  • Pattern  (検索するパターンを文字列でセットする)
  • IgnoreCase  (検索する時、大文字・小文字を区別するかをセットする)
  • Global  (検索文字列全体について検索(True)するか、最初の一致のみ検索(False)するかをセットする)

メソッド

最後にメソッドです。上記プログラムでは、testReplaceを実行しています。

testメソッド

testメソッドは、引数に対象となる文字列をセットすると、プロパティのパターンでマッチングを行い、マッチすればTrueを返します。

Replaceメソッド

Replaceメソッドでは、第一引数に対象となる文字列、第二引数にマッチした際に置き換える文字列をセットします。
第二引数は、CStrで文字列指定しないとエラーとなりました。

上記の例では、「くん」か「さん」があれば、「様」に置き換えるという処理になりました。対象文字列、パターン、置換のセルを変えれば正規表現の練習ができますので試してみてください。

Executeメソッド

Executeメソッドは、別のテストプログラムで解説します。

Executeメソッドは、Matchesコレクションを返します。
Matchesコレクションは、Matchオブジェクトのコレクションで、プロパティとしてCount(要素数)とItem(Mathオブジェクト)があります。
Matchオブジェクトには、以下のプロパティがあります。

  • FirstIndexプロパティ  検索対象の文字列内で一致が見つかった位置 (0始まり)
  • Lengthプロパティ  マッチした文字列の長さ
  • Valueプロパティ   マッチした値

以下がテストプログラムです。

Sub RegExpMacro2()
 
Dim reg As Object
Set reg = CreateObject("VBScript.RegExp")   'RegExpオブジェクト作成
Dim matchColl As Variant
Dim matchObj As Variant
Dim i As Long
 
Range("B7:D50") = ""
 
'正規表現
With reg
.Pattern = Range("B4")     'パターンをセット
.IgnoreCase = False     '大文字と小文字区別
.Global = True          '文字列全体を検索するか
End With
 
Range("G2") = reg.test(Range("B2"))     'testメソッド:成功すればTrueを返す
 
Set matchColl = reg.Execute(Range("B2")) 'Execute:Matchesコレクションを返す
 
i = 7
For Each matchObj In matchColl
Cells(i, "B") = matchObj.FirstIndex
Cells(i, "C") = matchObj.Length
Cells(i, "D") = matchObj.Value
i = i + 1
Next
 
End Sub

testメソッドまでは、前のコードとほぼ同じです。
このプログラムでは、Executeの戻り値として、Matchesコレクションを受けます。
(オブジェクトなのでSetを忘れないように!)

その後、For Each でMatchオブジェクトを取り出しながらプロパティを参照しています。
こちらも実際に作って動作を確認してみてください。

まとめ

ExcelVBAの正規表現では、RegExpオブジェクトを生成し、プロパティ値やメソッドを使って処理を行いました。
 RegExpオブジェクトの使い方とは別に、正規表現での文字列マッチング手法の知識も必要になりますので、初心者には難しいかもしれません。
 ただ、正規表現での文字列マッチングは、HTMLやCSVファイルなどで大量のテキストデータを扱う場合には非常に強力な武器となります。

 ExcelVBAを使って高度なプログラミングを目指す人は、是非挑戦してみてください。

タイトルとURLをコピーしました