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 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 für ein RegEx-Callout ist (?CNummer:Funktion), wobei sowohl Nummer als auch Funktion optional sind. 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.

Wenn Funktion weggelassen wird, muss der Funktionsname einer Variable namens pcre_callout zugewiesen werden. Wenn es sowohl eine globale als auch eine lokale Variable mit diesem Namen gibt, hat die lokale Variable Vorrang. Wenn pcre_callout nicht den Namen einer benutzerdefinierten Funktion enthält, werden RegEx-Callouts ohne Funktion ignoriert.

RegEx-Callout-Funktionen

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

RegEx-Callout-Funktionen akzeptieren bis zu 5 Parameter:

Diese Namen sind nur Beispiele. Es können beliebige Namen verwendet werden.

Warnung: Das Ändern der Eingabeparameter von RegExReplace() oder RegExMatch() während eines Aufrufs wird nicht unterstützt und kann zu unvorhersehbarem Verhalten führen.

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
}

Im obigen Beispiel wird Callout einmal für jede Teilzeichenkette aufgerufen, die mit dem Teil des Suchmusters vor dem RegEx-Callout übereinstimmt. Das \b wird verwendet, um 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 die Optionen des Suchmusters ein, um den Auto-Callout-Modus zu aktivieren. In diesem Modus werden RegEx-Callouts äquivalent zu (?C255) vor jedem Element im Suchmuster eingefügt. Das folgende Beispiel kann zum Debuggen von regulären Ausdrücken verwendet werden:

; 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 auszuwertendes 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 im 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. Um in solchen Fällen RegEx-Callouts zu ermöglichen, 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.