VB(A)

[정규식] 일치하는 문자열만 추출(lazy 모드)

당근쨈 2017. 2. 5. 23:20


질문글에서 알 수 있듯이 대괄호로 묶인 부분만 추출하면 되는 내용이다.

유의해야할 점이 대괄호가 이중으로 묶여있다는 사실. 이것이 두개 이상인 경우가 있다.


정규식에는 lazy 모드과 Greedy 모드가 있다.

문자 그대로 lazy는 패턴이 최소한으로 일치하는 패턴만 가져온다.

문자열을 검색하다가 패턴이 일치하면 그 자리에서 멈춘다.


반연 greedy 는 패턴이 일치하는 마지막 문자열에서야 멈춘다.

모든 패턴을 탐욕스럽게 검색한다는 뜻.

아래 그림에서 보면 lazy와 greedy의 차이를 볼 수 있다.


아래 그림은 lazy 모드로, 두개의 그룹으로 문자열을 추출하는 것을 볼 수 있다.

패턴이 일치하면 그 자리에서 멈추고 새로운 패턴을 찾아나선다.

Global 속성이 부여되지 않았다면 처음 패턴에서 문자열을 추출한 후 멈췄을 것이다.


아래 그림은 greedy 모드로, 문자열의 마지막까지 패턴이 일치하는 구간을 찾아나선다.

때문에 그룹이 하나밖에 생성되지 않는다.


비밀은 위 아래 그림의 단 하나의 차이점인 '?'

? 가 붙으면 lazy 모드, 붙지 않으면 greedy 모드니 필요한 경우에 따라 ? 를 붙이거나 떼면 된다. 쉽다.


아래는 사용자정의함수를 작성한 후 적용한 스크린샷과 코드이다.

코드의 한줄한줄마다 주석을 달아놨으니 해석하는 데는 어려움이 없을 것이다.




Function GetCDATA(temp As StringAs String
 
    Dim MySet As Object
    Dim i As Integer
    Dim v() As String
    
    With CreateObject("vbscript.regexp")    '정규식 선언
        .Global = True
        .Pattern = "(\[CDATA.*?\]\])"   '대괄호로 묶인 데이터를 Lazy 모드로 가져옴
        
        If .test(temp) Then '일치하는 패턴이 있을 때
        
            Set MySet = .Execute(temp)  '일치하는 패턴을 그룹으로 묶음
            
            ReDim v(MySet.Count - 1)    '그룹을 담아줄 배열 재선언
            
            For i = 0 To UBound(v)  '일치하는 문자열을 배열에 삽입
                v(i) = MySet.Item(i)
            Next i
            
            GetCDATA = Join(v, ", ")    '배열을 콤마로 연결하여 최종 출력
        
        Else    '패턴과 일치하는 문자열이 없으면 공란 출력
            GetCDATA = ""
            
        End If
        
    End With
    
End Function
 
cs


통합 문서1.xlsm