正規表現一致文字列色変更 

正規表現に一致する文字の色を変更する version1.0

下記ソースでは値のある範囲を対象とする。
正規表現パターンは使用の都度調べるといい。定数に入れて実行して。
応用として、一致パターン検出セルを結果シートに一覧化するなどができる。
SubをFunctionに変更して外部のシート走査関数と組み合わせると全シートを対象に処理できる。
Option Explicitを指定しておらず、変数宣言はちょこちょこ省略している。

※注意
ツール>参照設定
「Microsoft Office Regular Expressions 5.5」を有効化すること

'正規表現に一致する文字の色を変更する
Const PETTERN = "\d{5}"
Sub regexpHitStringChangeTextColor()
    '実行シート取得
    Dim s As Worksheet
    Set s = ActiveSheet
    
    '走査範囲取得
    Dim lastCellAddress As String: lastCellAddress = s.UsedRange(s.UsedRange.Count).Address
    Dim lastCellRow As String: lastCellRow = Range(lastCellAddress).Row
    Dim lastCellColumn As String: lastCellColumn = Range(lastCellAddress).Column
    
    Set regexp = CreateObject("VBScript.RegExp")
    
    For i = 1 To lastCellRow
        For j = 1 To lastCellColumn
            Set targetRange = s.Cells(i, j)
            With regexp
                '検索する正規表現条件
                .Pattern = PETTERN
                '大文字小文字の区別(True:しない、False:する)
                .IgnoreCase = False
                '文字列の最後まで検索(True:する、False:しない)
                .Global = True
                'セル文字列から正規表現での検索を行う
                Set regResult = .Execute(targetRange.Value)
                
                '1セル内に複数回見つかったらその分処理を回す
                For k = 0 To regResult.Count - 1
                   '見つかった箇所を取得
                    Set hit = regResult.Item(k)
                    '検索一致の先頭位置を取得
                    hitPosition = hit.FirstIndex
                    '検索一致文字列長を取得
                    hitLength = hit.Length
                    '検索一致部分の色変更
                    targetRange.Characters(Start:=hitPosition + 1, Length:=hitLength).Font.COLOR = RGB(255, 0, 0)
                Next
            End With
        Next
    Next
End Sub

このページ中によく使う正規表現パターンも載せておきたい。


指定文字列がパターンに一致するかどうかをチェック

文字列とパターンを渡して一致するかどうかを返す。

'#説明:指定された値が正規表現パターンに一致するかどうかを検証する
'#引数:text:検査文字列、pattern:正規表現パターン
'#戻値:真偽値(true:一致する、false:一致しない)
Function isRegexpHit(text As String, pattern As String)
    Set regexp = CreateObject("VBScript.RegExp")
    With regexp
         '検索する正規表現条件
         .pattern = pattern
        '大文字小文字の区別(True:しない、False:する)
        .IgnoreCase = False
        '文字列の最後まで検索(True:する、False:しない)
        .Global = True
        '戻り値
        isRegexpHit = .test(text)
    End With
End Function

指定文字列のうちパターンに一致した文字列をコレクションで返す

参照設定気を付けて。

'#説明:指定された値のうち正規表現パターンに一致するものをコレクションで返す
'#引数:text:検査文字列、pattern:正規表現パターン
'#戻値:コレクション(参照設定:Microsoft VBScript Regular Expressions 5.5)
Function regexpHitCollection(text As String, pattern As String)
    Set regexp = CreateObject("VBScript.RegExp")
    With regexp
         '検索する正規表現条件
         .pattern = pattern
        '大文字小文字の区別(True:しない、False:する)
        .IgnoreCase = False
        '文字列の最後まで検索(True:する、False:しない)
        .Global = True
        '戻り値
        Set regexpHitCollection = .Execute(text)
    End With
End Function

参考URL

https://qiita.com/grrrr/items/0b35b5c1c98eebfa5128


めもめもめーも。

正規表現チェッカーさん
https://ymori.com/regexcheck/

ドットはなにか一文字
アリス→ア.ス
アイリス→ア..ス

半角括弧はそのうちのいずれか
初雪、豪雪、大雪→[初豪]雪

範囲の場合はハイフンで最初と最後で繋ぐ
第1話、第3話、第5話、第6話→第[1-5]話

数字全部なら\dが使える、dはdigitの略。0~9を示す
第1話、第3話、第5話、第6話→第\d話

英数字とアンダーバーは\wを使う。
testA、testあ、test?、test1→test\w

ひらがなの範囲(最初から最後)は[ぁ-ん]
カタカナの範囲は(最初から最後)は[ァ-ヴ]
コンピュータは文字コードの順序で管理してるからこうなる。

正規表現のメタ文字は以下などがある。
.*+?\|^$[](){}

メタ文字そのものをマッチさせたい場合は「\」とセットで使う
\. \* \+ \? \\ ・・・など
これを「メタ文字をエスケープする」という。

test0.jpg、test1.jpg、testA.jpg、test1Ajpg→test\d.jpg
これだと「test1Ajpg」もマッチしてしまう。

test0.jpg、test1.jpg、testA.jpg、test1Ajpg→test\d\.jpg
こうすればOK。ドットをエスケープすることでドットのまま探してくれる。

\メタ文字 → メタ文字そのものを表す
\メタ文字以外 → 特殊な文字(数値とか英数字とか)を表す

\d:数字、\w:英数字、\s:空白、\t:タブ、\n:改行

どれか一文字にマッチさせたいときは[初豪]が使えたが、これが文字列の場合「|」を使う。
ビーフ、ポーク、フィッシュ、チキン→ビーフ|チキン

次のようにorの検索ワードを増やすことも可能
ビーフ、ポーク、フィッシュ、チキン→ビーフ|チキン|フィッシュ
半角スペースとか余計なもの入れるとマッチしなくなるから気を付けて。

ミルクティーかレモンティーをマッチさせたいとき、次の方法では失敗する
ミルクティー、アップルティー、レモンティー、シナモンティー→ミルク|レモンティー

正しくはこう。半角括弧で囲んであげて「|」で区切る。+括弧の外に接尾辞を続ける。
ミルクティー、アップルティー、レモンティー、シナモンティー→(ミルク|レモン)ティー

文字列の先頭だけをマッチさせたい場合・・・
赤巻紙、青巻紙、黄巻紙→^.巻紙
「^」は出現箇所によって役割が異なるので要注意。[^12]だったら1・2以外、という意味になる。

文字列の末尾だけをマッチさせたい場合・・・
赤巻紙、青巻紙、黄巻紙→.巻紙$
末尾を示すのでパターンの最後に「$」を付与する点がポイント

繰り返す文字へのマッチ。「*」は直前にあるものを0回以上繰り返す。
やった!、やったー!、やったーーーー!→やったー*!

次のパターンはどんな文字にでもマッチする
.*

最短マッチ
*?

「フィナンシェ」と「マドレーヌ」と「マカロン」→「.*」
これでいくと全部マッチしてしまう。最初の「と最後の」で全部をマッチさせてしまう。そういうとき・・・
「フィナンシェ」と「マドレーヌ」と「マカロン」→「.*?」
とすれば「と」を省いた形で3つマッチする

これを応用してHTMLのタグそのもののマッチもできる。
<h1>これはタイトルです。</h1>
<b>これは太字です。</b>
→<.*?>


例えば『』の括弧に囲まれた文字列のみマッチさせたい場合は
『.*』
というパターンを使える。これなら「」や【】に囲まれたものはマッチさせなくできる。

『これはタイトルです。』
「これはセリフです。」
『』
(これは注釈です)
→『.*』

1回以上繰り返す「前にあるもの」にマッチさせたい場合は+を使う。
先ほどのチェック文字列に対して『.+』をパターンとして使うと『』は抽出されなくなる。0文字を許容しないから。

*や+は前にある同じ文字ではなく「直前にあるもの」を繰り返すのでグループ化されていればそれを対象とできる。
アリス、鏡の中のアリス、鏡の中の鏡の中のアリス、鏡の中の鏡の中の鏡の中のアリス→(鏡の中の)+アリス
「鏡の中の」を1回以上繰り返す + 「アリス」で構成された文字列がヒットする。

あってもなくてもマッチさせたいときは?を使う
boy、girl、boys、girls→girls?
これで最後の「s」があってもなくてもマッチするから「girl」と「girls」を抽出できる

先読み~後ろに○○がついているときだけマッチ~
100円、令和3年、西暦2023年、第005回*→\d+(?=年)
マッチするのは数字の部分だけ(「年」は含まないぜ)
「●(?=〇)」←こういう構文

後読み~前に○○がついているときだけマッチ~
100円、令和3年、西暦2023年、第005回*→(?<=西暦)\d+
「(?<=〇)●」←こういう構文

否定的先読み~後ろに○○以外がついているときだけマッチ~
test.txt, test.jpg, test.png→test(?!\.txt)
ドットはエスケープしてる。「●(?!〇)」←こういう構文

否定的後読み~前に○○以外がついているときだけマッチ~
東京都港区
京都府京都市
東京都品川区
京都府宇治市
→(?<!東)京都.*
前が「東」以外の時「京都」となんでもいい1文字を0回以上繰り返す文字列にマッチする
これ、自力で作る時はまず「京都.*」の部分を作ってから「(?<!東)」の部分を作るのがよさそう。考え方の順序として

置換
学校のパソコンは、windowsだ。
書店でウィンドウズの本を見つけた。
家に帰ってWindowsの勉強をしよう。
秀丸の置換モードに検索ワードを「windows|Windows|ウィンドウズ」置換文字を「Windows」とする。これで置換できる。
正規表現チェッカーのページでもいい。

マッチした文字に文字を追加する
追加したい部分を「()」でグループ化してキャプチャする。このグループ化が重要。
今日は第1回の授業です。正規表現の授業は、第2回~第3回に行います。→(第\d回)
置換文字列→「$1」。これは固定値。もうこれ。言語によって「/1」だったりする。
これで
今日は「第1回」の授業です。正規表現の授業は、「第2回」~「第3回」に行います。
になる。

これがHTMLで太字にしたい場合、
<b>$1</b>
とすると
今日は<b>第1回</b>の授業です。正規表現の授業は、<b>第2回</b>~<b>第3回</b>に行います。
になる。


■実践
▼「だ。」「である。」を「です。」に変更する
チェック文字列:明日は晴れだ。熱くなりそうである。明日のおやつはアイスだ。
正規表現は「だ。|である。」、置換文字は「です。」とする。これで置換実行したらOK。

▼ダブルクォーテーションを鍵括弧に変換する
チェック文字列:"おはようございます"、"いただきます"、"ごちそうさまでした"
正規表現は「"(.*?)"」、置換文字は「「$1」」とする。
あ、なるほど。置換のときに置換文字列に「$1」を使うのはマッチした文字列を置換後も残したいときだ。

▼カンマ区切りの数字にマッチする
チェック文字列:
これは、¥10-です。
これは、¥1,234-です。
これは、¥123,456,789-です。
これは、¥12345678-です。
正規表現は「¥\d{1,3}(,\d{3})*-」。
置換する場合、正規表現は「¥(\d{1,3}(,\d{3})*)-」置換文字は「$1円」とする。
これ、置換するときは括弧を入れ子にしてる。外側から優先されるので
外側のを使う場合は「$1」、中の括弧にマッチしたものを使う場合は「$2」とする

▼時刻にマッチする1
チェック文字列:
10:20:30
23:59:59
1:20:30
12:300:00
30:60:99
正規表現は「\d{2}:\d{2}:\d{2}」。ありえない時間にも一致してしまうという弱点がある。

▼時刻にマッチする2
チェック文字列:上と同じ
正規表現は「([01]\d|2[0-3]):[0-5]\d:[0-5]\d」。各桁毎にパターンを用意している。長いしわかり辛えな。

▼日付にマッチする1
チェック文字列:
2022-12-25
2020-01-01
2020/10/10
2020-12.25
2022-13-45
正規表現は「\d{4}([\-\./])\d{2}\1\d{2}」
「()」はキャプチャの役割があるから月と日の間の記号はキャプチャしたものを「\1」で再利用している
これも時刻マッチ1のときみたいにありえない日付にもマッチしてしまう弱さがある。

▼日付にマッチする2
チェック文字列:上と同じ
正規表現は「\d{4}([\-\./])(0[1-9]|1[0-2])\1(0[1-9]|[12]\d|3[01])」。これでありえない日はマッチしなくできた。
あ、でも2,4,6,9月は31日がないところとかは考慮できていない。2月の29日とか。ま、しゃあない。

▼文字数チェック
チェック文字列:
abc
abcde
abcde_1
abcde1234
正規表現は「^[a-zA-Z0-9]{4,8}$」。
4桁以上8桁以下の英数字を探している。前後の「^」と「$」がないと部分一致するものもマッチしてしまうので、パスワードチェックの用途だったらこれは忘れないようにして。

▼郵便番号チェック
チェック文字列:
12-3456
123-4567
123-45678
1234-567
正規表現は「^\d{3}-\d{4}$」。
分かりやすくていい。これも先頭と末尾の「^」「$」と忘れないで。

▼メールアドレスチェック
チェック文字列:
test@example.com
test@examplecom
www.example.com
正規表現は「^[\w\-\.]+@[\w\-\.]+\.[a-zA-Z]+$」。
1文字以上の英数字か「-」、「@」、1文字以上の英数字か「-」、ドット、1文字以上のアルファベット

▼HTML要素マッチ
チェック文字列:
<h1>見出し1</h1> <b>太字</b> <b>abc <h2></h2> <h2>見出し?</h3>
<p><b>ほげ</b></p>
正規表現は「<(\w+)>.*</\1>」
キャプチャを使っているからタグのペアごとに探すことができる。
空の要素を探したい場合は正規表現を「<(\w+)></\1>」とする

▼URLにマッチ
チェック文字列:
htps://www.ymori.com/
http://www.ymori.com/
https://www.ymori.com/test/test.html&param=1
https://www.ymori.com/test/test.html#abc
正規表現は「https?://[\w\-\.~!#\$%&'\(\)\*\+,/;=?@\[\+」
すごいややこしく見えるけど、案外単純なことをしてる。httpもしくはhttpsから始まり、//のあとは角括弧で囲んだものを繰り返してるかどうかをみてる。m他文字をエスケープしてるせいですごい複雑に見えるけど、やってることはけっこう単純。

▼URLのホスト・ドメイン名にマッチ
チェック文字列:上と同じ
正規表現は「(?<=https?://)[\w\-\.]+(?=/.*)」


■SELECT句抽出
(?<=SELECT\s)[\w\d\s\,]+(?=\sFROM)
■FROM句抽出
(?<=FROM\s)[\w\d\s\,]+(?=\sWHERE)
■WHERE句抽出
(?<=WHERE\s)[\w\d\s\,\=\'あ-んァ-ヴ]+(?=\sORDER)
■条件抽出(条件は改行させておく必要あり)
\w+\s+=\s+\'?[\d\wあ-んァ-ヴ]+\'?


↓検証中(これっぽい。↓条件部分、もう少しメタ文字含んだ方がよさそう\\とか)
↓検証対象の文字列、改行させておかなくてもいい!
[\w\d]+\s?=\s?\'?[\d\wあ-んァ-ヴ]+\'?
↓検証中
SELECT aa, bb, cc, d1f FROM hogehoe WHERE cc = 1 AND 
bb = 'ほヴ' OR 
d1f=44 OR
aa = 'ほげ' ORDER BY cc LIMIT 10

▼正規表現(要素だけとりだす))
(?<=\>)[あ-ん\w\,\.\/\\\\\^\-\s]+(?=\<)
▼検索文字
<h1>ほげほげ</h1><p>あいうえお<b>かきくけこ ,./\^-09876</b>さしすせそ</p>


コメント