VBAのRegExpでマッチングできないとき
はじめに
他の言語やVS CodeではマッチングするのにVBAでできなくなることがある。
今回分かったのはそれが複数行にわたる場合である。
入力テキスト
とりあえず好きなラグトレインの歌詞を使用する。
離れ離れの街を繋ぐ列車は行ってしまったね 失くした言葉を知らないなら ポケットで握りしめて あがいた息を捨てて延びる今日は眠って誤魔化せ 失くした言葉を知らないなら 各駅停車に乗り込んで 夕方と退屈のお誘いを断って 一人きり 路地裏は決して急がないで ほら 横断歩道も待ってくれと言ってる 見張る街角があなたを引き留めてく 離れ離れの街を繋ぐ列車は行ってしまったね 失くした言葉を知らないなら ポケットで握りしめて あがいた夢を捨てて揺れる今日は眠って誤魔化せ 失くした言葉を知らないなら 各駅停車に乗り込んで 夕方の駅のホームはひどく混み合って ひとり占めできるまで休憩して欲しくて また 集団下校があなたを急かしている ほら 自動改札は待ってくれと言ってる 塞がる両手があなたを引き留めてく あがいた夢を捨てて揺れる今日は眠って誤魔化せ 失くした言葉を知らないなら 各駅停車に乗り込んで 離れた街と街を繋ぐ列車が 呼んだ風に飛ばされないでいてくれ 失くした言葉はそのままでいいよ 揺れる列車に身を任せて欲しいから 離れ離れの街を 離れ離れの街を繋ぐ列車は行ってしまったね 失くした言葉を知らないなら ポケットで握りしめて あがいた息を捨てて延びる今日は眠って誤魔化せ 失くした言葉を知らないなら 各駅停車で旅をして
やりたいこと
「ポケットで握りしめて」に続く「あがいた息を捨てて延びる今日は眠って誤魔化せ」のみ対象に下記の赤字部のみを抜き出す。青字部は無視する。
離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいた息を捨てて延びる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで
夕方と退屈のお誘いを断って
一人きり 路地裏は決して急がないで
ほら 横断歩道も待ってくれと言ってる
見張る街角があなたを引き留めてく
離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいた夢を捨てて揺れる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで
夕方の駅のホームはひどく混み合って
ひとり占めできるまで休憩して欲しくて
また 集団下校があなたを急かしている
ほら 自動改札は待ってくれと言ってる
塞がる両手があなたを引き留めてく
あがいた夢を捨てて揺れる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで
離れた街と街を繋ぐ列車が
呼んだ風に飛ばされないでいてくれ
失くした言葉はそのままでいいよ
揺れる列車に身を任せて欲しいから
離れ離れの街を
離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいた息を捨てて延びる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車で旅をして
普通にやってみる
VS Codeにパターンを入力するとハイライトされる。
だがVBAに実装してもうまくいかない。
Option Explicit Sub main() Dim re As New RegExp With re .Global = True .IgnoreCase = True .MultiLine = False .Pattern = "ポケットで握りしめて\nあがいた(.)を捨てて(.{3})今日は眠って誤魔化せ" End With Dim fso As New FileSystemObject Dim txt As String txt = fso.OpenTextFile("H:\2021-06-21_VBA_RegExp\ラグトレイン.txt").ReadAll Debug.Print re.Test(txt) End Sub
解決方法
この場合、パターンの改行を\n
ではなくvbCrLf
を使うと解決する。
re.Pattern = "ポケットで握りしめて" & vbCrLf & "あがいた(.)を捨てて(.{3})今日は眠って誤魔化せ"
なお、デフォルトでは.txt
がUTF-8
だと盛大に文字化けしてマッチングしない。
最終的なコード
Option Explicit Sub main() Dim re As New RegExp With re .Global = True .IgnoreCase = True .MultiLine = False .Pattern = "ポケットで握りしめて" & vbCrLf & "あがいた(.)を捨てて(.{3})今日は眠って誤魔化せ" End With Dim fso As New FileSystemObject Dim txt As String Dim match_ As Match Dim matches_ As MatchCollection txt = fso.OpenTextFile("H:\2021-06-21_VBA_RegExp\ラグトレイン.txt").ReadAll Set matches_ = re.Execute(txt) For Each match_ In matches_ Debug.Print "1st match:" & match_.SubMatches(0) & vbCrLf & "2nd match:" & match_.SubMatches(1) & vbCrLf Next match_ End Sub '1st match:息 '2nd match:延びる ' '1st match:夢 '2nd match:揺れる ' '1st match:息 '2nd match:延びる