freedom-_-qの勉強履歴

メモ書きが主になるかと思います。勉強強制のために一日一記事目指してます。頭良くないので間違いが多々あるかと思います。

VBAのRegExpでマッチングできないとき

はじめに

他の言語やVS CodeではマッチングするのにVBAでできなくなることがある。
今回分かったのはそれが複数行にわたる場合である。

入力テキスト

とりあえず好きなラグトレインの歌詞を使用する。

離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいた息を捨てて延びる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで

夕方と退屈のお誘いを断って
一人きり 路地裏は決して急がないで
ほら 横断歩道も待ってくれと言ってる
見張る街角があなたを引き留めてく

離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいた夢を捨てて揺れる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで

夕方の駅のホームはひどく混み合って
ひとり占めできるまで休憩して欲しくて
また 集団下校があなたを急かしている
ほら 自動改札は待ってくれと言ってる
塞がる両手があなたを引き留めてく

あがいた夢を捨てて揺れる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで

離れた街と街を繋ぐ列車が
呼んだ風に飛ばされないでいてくれ
失くした言葉はそのままでいいよ
揺れる列車に身を任せて欲しいから

離れ離れの街を

離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいた息を捨てて延びる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車で旅をして

やりたいこと

「ポケットで握りしめて」に続く「あがいた息を捨てて延びる今日は眠って誤魔化せ」のみ対象に下記の赤字部のみを抜き出す。青字部は無視する。

離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいたを捨てて延びる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで

夕方と退屈のお誘いを断って
一人きり 路地裏は決して急がないで
ほら 横断歩道も待ってくれと言ってる
見張る街角があなたを引き留めてく

離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいたを捨てて揺れる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで

夕方の駅のホームはひどく混み合って
ひとり占めできるまで休憩して欲しくて
また 集団下校があなたを急かしている
ほら 自動改札は待ってくれと言ってる
塞がる両手があなたを引き留めてく

あがいたを捨てて揺れる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車に乗り込んで

離れた街と街を繋ぐ列車が
呼んだ風に飛ばされないでいてくれ
失くした言葉はそのままでいいよ
揺れる列車に身を任せて欲しいから

離れ離れの街を
離れ離れの街を繋ぐ列車は行ってしまったね
失くした言葉を知らないなら ポケットで握りしめて
あがいたを捨てて延びる今日は眠って誤魔化せ
失くした言葉を知らないなら 各駅停車で旅をして

普通にやってみる

VS Codeにパターンを入力するとハイライトされる。

f:id:freedom-_-q:20210621230111p:plain

だが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})今日は眠って誤魔化せ"

なお、デフォルトでは.txtUTF-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:延びる