정규 표현식 Callouts [AHK_L 14+]

정규 표현식 외부호출(RegEx Callouts)은 정규 표현식 일치 작업 중간에 임시로 제어를 스크립트에 넘기는 수단을 제공합니다. PCRE-표준 callout 특징에 관한 더 자세한 정보는 pcre.txt를 참조하십시오.

RegEx 콜아웃은 현재 RegExMatch() 그리고 RegExReplace()만 지원합니다.

목차

구문

오토핫키에서 RegEx callout 구문은 (?CNumber:Function)입니다. NumberFunction 모두 선택적입니다. 쌍점 ':'은 Function가 지정되었을 경우에만 허용됩니다. Number를 생략하면 선택적입니다. Function가 지정되었지만 사용자-정의 함수의 이름이 아니면, 컴파일 에러가 일어나고 패턴-일치가 시작되지 않습니다.

Function을 생략하면, 함수 이름을 븐드시 pcre_callout이라는 이름의 변수에 지정해야 합니다. 이 이름으로 전역 변수와 지역 변수가 모두 존재하면, 지역 변수가 우선 순위를 갖습니다. pcre_callout에 사용자-정의 함수 이름이 없으면, Function이 생략된 RegEx callouts은 무시됩니다.

RegEx Callout 함수

Function(Match, CalloutNumber, FoundPos, Haystack, NeedleRegEx)
{
    ...
}

RegEx callout 함수는 매개변수를 5 개 까지 정의할 수 있습니다:

이 이름들은 그냥 제시 용일 뿐입니다. 실제 이름은 다를 수 있습니다.

Warning: Changing the input parameters of RegExReplace() or RegExMatch() during a call is unsupported and may cause unpredictable behaviour.

패턴-일치는 RegEx 콜아웃 함수의 결과에 따라 계속 진행되거나 실패합니다:

예를 들어:

Haystack := "The quick brown fox jumps over the lazy dog."
RegExMatch(Haystack, "i)(The) (\w+)\b(?CCallout)")
Callout(m) {
    MsgBox m=%m%`nm1=%m1%`nm2=%m2%
    return 1
}

위의 예제에서, Callout는 RegEx 콜아웃 앞의 패턴 일부에 부합하는 부문자열마다 한 번씩 호출됩니다. \b는 부합에서 불완전한 단어들을 배제하는 데 사용됩니다. 예를 들어 The quic, The qui, The qu, 등등은 단어가 아니므로 제외됩니다.

EventInfo

A_EventInfo를 통하여 pcre_callout_block 구조체에 접근하면 추가 정보를 얻을 수 있습니다 .

version           := NumGet(A_EventInfo,  0, "Int")
callout_number    := NumGet(A_EventInfo,  4, "Int")
offset_vector     := NumGet(A_EventInfo,  8)
subject           := NumGet(A_EventInfo,  8 + A_PtrSize)
subject_length    := NumGet(A_EventInfo,  8 + A_PtrSize*2, "Int")
start_match       := NumGet(A_EventInfo, 12 + A_PtrSize*2, "Int")
current_position  := NumGet(A_EventInfo, 16 + A_PtrSize*2, "Int")
capture_top       := NumGet(A_EventInfo, 20 + A_PtrSize*2, "Int")
capture_last      := NumGet(A_EventInfo, 24 + A_PtrSize*2, "Int")
pad := A_PtrSize=8 ? 4 : 0  ; Compensate for 64-bit data alignment.
callout_data      := NumGet(A_EventInfo, 28 + pad + A_PtrSize*2)
pattern_position  := NumGet(A_EventInfo, 28 + pad + A_PtrSize*3, "Int")
next_item_length  := NumGet(A_EventInfo, 32 + pad + A_PtrSize*3, "Int")
if (version >= 2)
    mark   := StrGet(NumGet(A_EventInfo, 36 + pad + A_PtrSize*3, "Int"), "UTF-8")

더 자세한 정보는 pcre.txt, NumGet() 그리고 A_PtrSize를 참조하십시오.

Auto-Callout

패턴의 옵션에 C를 포함하면 auto-callout 모드가 켜집니다. 이 모드에서 (?C255)와 동등한 RegEx 콜아웃이 패턴의 각 항목 앞에 삽입됩니다. 예를 들어, 다음 템플릿을 사용하면 정규 표현식을 디버그할 수 있습니다:

; 기본 RegEx 콜아웃 함수를 설정합니다.
pcre_callout := "DebugRegEx"

; 자동-콜아웃 옵션 C를 가지고 RegExMatch를 호출합니다.
RegExMatch("xxxabc123xyz", "C)abc.*xyz")

DebugRegEx(Match, CalloutNumber, FoundPos, Haystack, NeedleRegEx)
{
    ; 다음 필드들에 대한 설명은 pcre.txt를 참조하십시오.
    start_match       := NumGet(A_EventInfo, 12 + A_PtrSize*2, "Int")
    current_position  := NumGet(A_EventInfo, 16 + A_PtrSize*2, "Int")
    pad := A_PtrSize=8 ? 4 : 0
    pattern_position  := NumGet(A_EventInfo, 28 + pad + A_PtrSize*3, "Int")
    next_item_length  := NumGet(A_EventInfo, 32 + pad + A_PtrSize*3, "Int")

    ; 다음과 같이 표시: >>현재 부합<<.
    _HAYSTACK:=SubStr(Haystack, 1, start_match)
        . ">>" SubStr(Haystack, start_match + 1, current_position - start_match)
        . "<<" SubStr(Haystack, current_position + 1)
    
    ; 다음과 같이 표시: >>평가될 다음 항목<<.
    _NEEDLE:=  SubStr(NeedleRegEx, 1, pattern_position)
        . ">>" SubStr(NeedleRegEx, pattern_position + 1, next_item_length)
        . "<<" SubStr(NeedleRegEx, pattern_position + 1 + next_item_length)
    
    ListVars
    ; 계속하려면 Pause를 누르십시오.
    Pause
}

논평

RegEx 콜아웃은 현재의 의사-쓰레드에서 실행됩니다. 그러나 RegEx 콜아웃 함수가 반환된 후에 A_EventInfo의 이전 값이 복구됩니다. RegExMatch() 또는 RegExReplace()가 돌아오기 바로 전까지 ErrorLevel은 설정되지 않습니다.

PCRE는 어떤 경우에 부합이 불가능하다고 판단하면 일찍 취소되도록 최적화되어 있습니다. 그런 경우라면 모든 RegEx 콜아웃에 대하여 이런 최적화를 끌 필요가 있습니다. 패턴의 처음에 (*NO_START_OPT) 를 지정하면 됩니다. 이 기능은 [v1.1.05] 이상을 요구합니다.