정규 표현식 Callouts [v1.0.90+]
외부호출(Callouts)은 정규 표현식 일치 작업 중간에 임시로 제어를 스크립트에 넘기는 수단을 제공합니다. PCRE-표준 callout 특징에 관한 더 자세한 정보는 pcre.txt를 참조하십시오.
콜아웃은 현재 RegExMatch 그리고 RegExReplace만 지원합니다.
구문
오토핫키에서 callout 구문은 (?CNumber:Function)입니다. Number와 Function 모두 선택적입니다. 쌍점 ':'은 Function이 지정되었을 경우에만 허용됩니다. Number를 생략하면 선택적입니다. Function이 지정되었지만 사용자-정의 함수의 이름이 아니면, 컴파일 에러가 일어나고 패턴-일치가 시작되지 않습니다.
Function을 생략하면, 함수 이름을 반드시 pcre_callout이라는 이름의 변수에 지정해야 합니다. 이 이름으로 전역 변수와 지역 변수가 모두 존재하면, 지역 변수가 우선 순위를 갖습니다. pcre_callout에 사용자-정의 함수 이름이 없으면, Function이 생략된 외부호출은 무시됩니다.
Callout 함수
Function(Match, CalloutNumber, FoundPos, Haystack, NeedleRegEx) { ... }
Callout 함수는 매개변수를 다섯 개까지 정의할 수 있습니다:
- Match: 필요하면 배열 변수의 생성도 포함해서 RegExMatch의 UnquotedOutputVar와 동등합니다.
- CalloutNumber: 콜아웃의 Number를 받습니다.
- FoundPos: 현재의 잠재적인 부합의 위치를 받습니다.
- Haystack: RegExMatch 또는 RegExReplace에 건네어진 Haystack을 받습니다.
- NeedleRegEx: RegExMatch 또는 RegExReplaceReceives에 건네어진 NeedleRegEx를 받습니다.
이 이름들은 그냥 제시 용일 뿐입니다. 실제 이름은 다를 수 있습니다.
패턴-일치는 콜아웃 함수의 결과에 따라 계속 진행되거나 실패합니다:
- 콜아웃 함수가 0을 돌려주거나 숫치 값을 돌려주지 않으면, 부합은 정상대로 진행됩니다.
- 함수가 1 이상을 돌려주면, 현재 위치의 부합은 실패합니다. 그러나 다른 부합의 가능성 테스트는 계속 진행됩니다.
- 함수가 -1을 돌려주면, 부합을 포기합니다.
- 함수가 -1보다 작은 값을 돌려주면, PCRE 에러 코드로 간주하고 부합을 포기합니다. RegExMatch는 빈 문자열을 돌려주는 반면에, RegExReplace는 원래의 Haystack을 돌려줍니다. 어느 경우든, ErrorLevel에 에러 코드가 담깁니다.
예를 들어:
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 }
위의 예제에서, Func는 콜아웃 앞의 패턴 일부에 부합하는 부문자열마다 한 번씩 호출됩니다. \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 ; 64-비트 데이터 정렬을 위하여 보완합니다. 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)와 동등한 콜아웃이 패턴의 각 항목 앞에 삽입됩니다. 예를 들어, 다음 템플릿을 사용하면 정규 표현식을 디버그할 수 있습니다:
; 기본 콜아웃 함수를 설정합니다. 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 }
논평
콜아웃은 현재의 의사-쓰레드에서 실행됩니다. 그러나 콜아웃 함수가 반환된 후에 A_EventInfo의 이전 값이 복구됩니다. RegExMatch 또는 RegExReplace가 돌아오기 바로 전까지 ErrorLevel은 설정되지 않습니다.
PCRE는 어떤 경우에 부합이 불가능하다고 판단되면 일찍 취소되도록 최적화되어 있습니다. 그런 경우라면 모든 콜아웃에 대하여 이런 최적화를 끌 필요가 있습니다. 패턴의 처음에 (*NO_START_OPT)
를 지정하면 됩니다. 이 기능은 v1.1.05 이상을 요구합니다.