Callouts in Regulären Ausdrücken [AHK_L 14+]

RegEx-Callouts bieten die Möglichkeit, die Kontrolle vorübergehend an das Skript zu übergeben, während ein Suchmuster (regulärer Ausdruck) ausgewertet wird. Detaillierte Informationen über das PCRE-Standard-Callout-Feature finden Sie unter pcre.txt.

RegEx-Callouts werden zurzeit nur von RegExMatch() und RegExReplace() unterstützt.

Inhaltsverzeichnis

Syntax

Die Syntax zum Definieren eines RegEx-Callouts ist (?CNummer:Funktion) - hierbei ist Nummer und Funktion optional. Der Doppelpunkt (:) ist nur erlaubt, wenn Funktion angegeben ist, und optional, wenn Nummer weggelassen wird. Wenn Funktion angegeben ist, aber nicht der Name einer benutzerdefinierten Funktion ist, wird ein Kompilierungsfehler auftreten und die Suchmusterauswertung abgebrochen.

Lässt man Funktion weg, muss der Funktionsname in einer Variable namens pcre_callout angegeben werden. Wenn sowohl eine globale als auch lokale Variable mit diesem Namen existieren, hat die lokale Variable Vorrang. Wenn pcre_callout nicht den Namen einer benutzerdefinierten Funktion enthält, werden RegEx-Callouts, die Funktion weglassen, ignoriert.

RegEx-Callout-Funktionen

Funktion(Match, CalloutNummer, FundPos, Heuhaufen, NadelRegEx)
{
    ...
}

RegEx-Callout-Funktionen akzeptieren bis zu 5 Parameter:

Diese Namen dienen nur als Beispiel. Es können beliebige Namen verwendet werden.

Die Suchmusterauswertung kann je nach Rückgabewert der RegEx-Callout-Funktion fortgesetzt werden oder fehlschlagen:

Zum Beispiel:

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

Das Beispiel oben bewirkt, dass Callout einmal für jede Teilzeichenkette, die mit dem Teil des Suchmusters vor dem RegEx-Callout übereinstimmt, aufgerufen wird. Das \b dient dazu, unvollständige Wörter in Übereinstimmungen wie The quic, The qui, The qu, etc. auszuschließen.

EventInfo

Zusätzliche Informationen erhalten Sie durch Zugriff auf die pcre_callout_block-Struktur via A_EventInfo.

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  ; Ausgleich für die 64-Bit-Datenausrichtung.
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")

Weitere Informationen finden Sie unter pcre.txt, NumGet() und A_PtrSize.

Auto-Callout

Fügen Sie C in den Optionen des Suchmusters ein, um den Auto-Callout-Modus zu aktivieren. In diesem Modus werden RegEx-Callouts in Form von (?C255) vor jedem Element im Suchmuster eingefügt. Das folgende Beispiel kann genutzt werden, um reguläre Ausdrücke zu debuggen:

; Standard-RegEx-Callout-Funktion setzen.
pcre_callout := "DebugRegEx"

; RegExMatch mit der Auto-Callout-Option C aufrufen.
RegExMatch("xxxabc123xyz", "C)abc.*xyz")

DebugRegEx(Match, CalloutNumber, FoundPos, Haystack, NeedleRegEx)
{
    ; Beschreibungen dieser Felder finden Sie unter 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")

    ; Aktuelle Übereinstimmung >>hervorheben<<.
    _HAYSTACK:=SubStr(Haystack, 1, start_match)
        . ">>" SubStr(Haystack, start_match + 1, current_position - start_match)
        . "<<" SubStr(Haystack, current_position + 1)
    
    ; Nächstes auszuwertende Element >>hervorheben<<.
    _NEEDLE:=  SubStr(NeedleRegEx, 1, pattern_position)
        . ">>" SubStr(NeedleRegEx, pattern_position + 1, next_item_length)
        . "<<" SubStr(NeedleRegEx, pattern_position + 1 + next_item_length)
    
    ListVars
    ; Drücken Sie PAUSE, um fortzufahren.
    Pause
}

Bemerkungen

RegEx-Callouts werden auf dem aktuellen Pseudo-Thread ausgeführt, allerdings wird der vorherige Wert von A_EventInfo wiederhergestellt, wenn die RegEx-Callout-Funktion zurückkehrt. ErrorLevel wird erst gesetzt, wenn RegExMatch() oder RegExReplace() zurückkehrt.

PCRE ist so optimiert, dass es in einigen Fällen vorzeitig abbricht, wenn es feststellt, dass eine Übereinstimmung nicht möglich ist. Damit RegEx-Callouts in solchen Fällen aufgerufen werden können, müssen diese Optimierungen durch Angabe von (*NO_START_OPT) am Anfang des Suchmusters deaktiviert werden. Dies benötigt [v1.1.05] oder höher.