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

Callouts bieten die Möglichkeit, inmitten der Mustererkennung die Kontrolle vorübergehend an das Skript zu übergeben. Für detaillierte Informationen über die PCRE-Standard-Callout-Funktion, siehe pcre.txt.

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

Inhaltsverzeichnis

Syntax

Die Syntax zum Definieren eines Callouts ist (?CNummer:Funktion); Nummer und Funktion sind optional. Der Doppelpunkt (:) ist nur erlaubt, wenn Funktion angegeben ist, und optional, wenn Nummer weggelassen wird. Wenn die Funktion angegeben ist, aber nicht der Name einer benutzerdefinierten Funktion ist, dann erscheint ein Kompilierungsfehler und die Mustererkennung startet nicht.

Lässt man Funktion weg, muss der Funktionsname in einer Variable namens pcre_callout angegeben werden. Existiert sowohl eine globale als auch lokale Variable mit diesem Namen, gilt vorrangig die lokale Variable. Enthält pcre_callout nicht den Namen einer benutzerdefinierten Funktion, werden Callouts, die Funktion weglassen, ignoriert.

Callout-Funktionen

Funktion(Übereinstimmung, Calloutnummer, Fundposition, Heuhaufen, NadelRegEx)
{
    ...
}

Callout-Funktionen können bis zu 5 Parameter definieren:

Diese Namen sind nur zweckmäßig. Die tatsächlichen Namen können variieren.

Die Mustererkennung kann erfolgen oder fehlschlagen, abhängig vom Rückgabewert der Callout-Funktion:

Zum Beispiel:

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

Im oberen Beispiel wird Funktion für jede Teilzeichenkette einmal aufgerufen, die mit dem Teil des Musters vor dem Callout übereinstimmt. Mit \b können unvollständige Wörter in Übereinstimmungen wie The quic, The qui, The qu, etc. ausgeschlossen werden.

EventInfo

Es stehen zusätzliche Informationen zur Verfügung, wenn man per A_EventInfo auf die pcre_callout_block-Struktur zugreift.

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 können unter pcre.txt, NumGet() und A_PtrSize gefunden werden.

Auto-Callout

Das Einfügen von C in den Optionen des Musters aktiviert den Auto-Callout-Modus. Bei diesem Modus werden Callouts in Form von (?C255) vor jedem Element im Muster eingefügt. Das folgende Beispiel zeigt, wie man mit Callouts reguläre Ausdrücke debuggen kann:

; Setzt die Standard-Callout-Funktion.
pcre_callout := "DebugRegEx"

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

DebugRegEx(Übereinstimmung, Calloutnummer, Fundposition, Heuhaufen, NadelRegEx)
{
    ; Siehe pcre.txt, um mehr über diese Felder zu erfahren.
    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")

    ; Betont die >>aktuelle Übereinstimmung<<.
    _HEUHAUFEN:=SubStr(Heuhaufen, 1, start_match)
        . ">>" SubStr(Heuhaufen, start_match + 1, current_position - start_match)
        . "<<" SubStr(Heuhaufen, current_position + 1)
    
    ; Betont das >>nächste auszuwertende Element<<.
    _NADEL:=  SubStr(NadelRegEx, 1, pattern_position)
        . ">>" SubStr(NadelRegEx, pattern_position + 1, next_item_length)
        . "<<" SubStr(NadelRegEx, pattern_position + 1 + next_item_length)
    
    ListVars
    ; Drücken Sie PAUSE, um fortzufahren.
    Pause
}

Bemerkungen

Callouts werden auf den aktuellen Pseudo-Thread ausgeführt. Der vorherige Wert von A_EventInfo wird aber wiederhergestellt, nachdem die Callout-Funktion einen Wert zurückgegeben hat. ErrorLevel wird nicht gesetzt, bis RegExMatch() oder RegExReplace() einen Wert zurückgibt.

PCRE wurde optimiert, um in einigen Fällen früh abbrechen zu können, wenn es feststellt, dass eine Übereinstimmung nicht möglich ist. Damit Callouts in solchen Fällen aufgerufen werden können, müssen diese Optimierungen deaktiviert werden, indem man (*NO_START_OPT) an den Anfang des Musters setzt. Das benötigt [v1.1.05] oder höher.