ヤマ括弧でくくられたテキストを抽出(入れ子)
いつもお世話になっています。VBA学習者です(手短に説明するため文章がぶっきらぼうになることをご容赦ください)。
以下のようなテキストがあったとします。
サンプルテキストA:
test <sample_1> test <sample_2> test.
このテキストから括弧で括られた部分(ここでは「ユニット」と呼びます)を取り出すのは比較的容易です。
しかし、「サンプルテキストB」のように「ユニット」が入れ子になっている場合にも対応する必要があるため以下のコードを書きました。
これでとりあえず、入れ子の一番外殻のユニットを抽出することができました(「結果A」がシートに書き出されます)。
ここから更に、入れ子になっている内側のユニットも取り出したいのですが、これが意外とうまくいきません。
「結果B」のような結果を得るには、どのようにしたらよいでしょうか。
必ずしも、下に示した処理方法にこだわるものではないので、もっと良いアイデアがあれば大歓迎です!
※ここに示したサンプルは1行のみですが、実際には数千行(ユニットがない行も含む)からなるファイルをいくつも連続して処理するので、出来るだけシンプルに高速で処理できるようにしたいと思っています。
サンプルテキストB:
Test <if([control],<if([control],<if([test],a,b)>,c)>,<if([control],d,e)>> test <if([control],<if([control],f,g)>,<if([control],h,i)>><if([control],j,k)>.
結果A:
<if([control],<if([control],<if([test],a,b)>,c)>,<if([control],d,e)>>
<if([control],<if([control],f,g)>,<if([control],h,i)>>
<if([control],j,k)>
結果B:
<if([control],<if([control],<if([test],a,b)>,c)>,<if([control],d,e)>>
<if([control],<if([control],f,g)>,<if([control],h,i)>>
<if([control],j,k)>
<if([control],<if([test],a,b)>,c)>
<if([test],a,b)>
<if([control],d,e)>
<if([control],f,g)>
<if([control],h,i)>
Sub テスト()
Dim i As Long
Dim j As Long
'テキストファイル内の行を格納する変数
Dim textLine As String
'テキストの文字数を格納
Dim letterCount As Integer
'ヤマ括弧の数を数えるカウンタ用
Dim bracketCounter1 As Integer
Dim bracketCounter2 As Integer
'括弧の位置を格納する変数
Dim bracketPosition1 As Integer
Dim bracketPosition2 As Integer
'「<」から「>」までのテキストを格納
Dim textFromToBracket As String
'括弧の見つかった位置を格納する配列
Dim unitArray() As String
'bracketArray1()の要素数のカウンタ
Dim inArrayCounter As Integer
'textLineにテスト用テキストを格納
textLine = "Test <if([control],<if([control],<if([test],a,b)>,c)>,<if([control],d,e)>> test <if([control],<if([control],f,g)>,<if([control],h,i)>><if([control],j,k)>."
letterCount = Len(textLine)
'先頭から「< 」と「>」 をカウントし、の数が一致したところが1ユニット
For i = 1 To letterCount
'Midで1文字ずつとりだしつつ「<」を検索
If Mid(textLine, i, 1) = "<" Then
bracketCounter1 = bracketCounter1 + 1
'1つ目の「<」の位置を格納
If bracketCounter1 = 1 Then
bracketPosition1 = i
End If
End If
'Midで1文字ずつとりだしつつ「>」を検索
If Mid(textLine, i, 1) = ">" Then
bracketCounter2 = bracketCounter2 + 1
End If
'ヤマ括弧の数が0以外で、括弧始め/閉じの数が一致したら
If bracketCounter1 + bracketCounter2 > 0 And bracketCounter1 = bracketCounter2 Then
'その時点の「>」の位置を格納
bracketPosition2 = i
'bracketPosition1からbracketPosition2までのテキストを切り出し
textFromToBracket = Mid(textLine, bracketPosition1, bracketPosition2 - bracketPosition1 + 1)
'配列の要素数を1つずつ増やしながらユニットを格納
inArrayCounter = inArrayCounter + 1
ReDim Preserve unitArray(inArrayCounter)
unitArray(inArrayCounter) = textFromToBracket
'bracketCounter1とbracketCounter2を初期化
bracketCounter1 = 0
bracketCounter2 = 0
End If
Next
'以下配列に格納したユニットを書き込み
For j = 1 To UBound(unitArray)
Cells(j, 1).Value = unitArray(j)
Next j
End Sub
お礼
回答ありがとうございます。 Replaceでは限界があったのですね。 こんなに短くなるとは思いませんでした。 どうもありがとうございました。