StringRegExpReplace(), mehrere Treffer mit verschiedenen Werten ersetzen.

  • Hallo Community,

    ich beschäftige mich zurzeit mit RegEx. Nun schwebt mir vor, ein AutoIt-RegEx-Tester zu erstellen. Damit kann ich verschiedene Szenarien üben und dies dann vielleicht auch anderen sinnvoll weitergeben / beibringen.

    Inhalt:
    Ein Beispieltext in RichEdit ist vorhanden. Sowie ein Inputfeld für den Regulären Ausdruck, der versucht werden soll. Ein Button zur Ausführung und schon sollen die Treffer im Text des RichEdits entsprechend markiert (ge'highlight'et) werden. So viel zur Vorstellung.

    Die bisherige Lösung:

    Spoiler anzeigen
    [autoit]


    #region includes
    #include <Array.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiRichEdit.au3>
    #include <WindowsConstants.au3>
    #endregion

    [/autoit] [autoit][/autoit] [autoit]

    #region init
    $sPre = "{\rtf1"
    $sText = "Hier steht nun ein entsprechender TEST-Text, welcher ein Mini-Highlighting durch RegEx ermöglichen soll. Dabei sind die folgenden Zahlen- bzw. /Ziffernfolgen einfach nur zum Test oder auch üben da. Es dreht sich um den 04.04.2014 (2014-04-04 als Alternativschreibweise). Ein Problem stellt sich mir, bei der Ersetzung!"
    $sSuf = "}"
    #endregion

    [/autoit] [autoit][/autoit] [autoit]

    #region GUI
    $hGui = GUICreate( "RegEx-Tester", 700, 450, Default, Default )
    $hRichEdit = _GUICtrlRichEdit_Create( $hGui, $sPre & $sText & $sSuf, 10, 10, 680, 350, BitOR( $ES_MULTILINE, $ES_READONLY ), $WS_EX_TRANSPARENT )
    $iInput = GUICtrlCreateInput( "", 10, 355, 670, 35 )
    GUICtrlSetFont( -1, 18 )
    $oBtn = GUICtrlCreateButton( "Any matches?", 10, 405, 670, 35 )
    GUICtrlSetFont( -1, 18 )
    GUISetState()
    #endregion

    [/autoit] [autoit][/autoit] [autoit]

    #region events (while)
    While 1
    $eMsg = GUIGetMsg()
    Switch $eMsg
    Case $GUI_EVENT_CLOSE
    GUIDelete()
    Exit
    Case $oBtn
    _getMatches()
    EndSwitch
    WEnd
    #endregion

    [/autoit] [autoit][/autoit] [autoit]

    #region functions
    Func _reset()
    ; reset
    $sPre = "{\rtf1"
    $sText = "Hier steht nun ein entsprechender TEST-Text, welcher ein Mini-Highlighting durch RegEx ermöglichen soll. Dabei sind die folgenden Zahlen- bzw. /Ziffernfolgen einfach nur zum Test oder auch üben da. Es dreht sich um den 04.04.2014 (2014-04-04 als Alternativschreibweise). Ein Problem stellt sich mir, bei der Ersetzung!"
    $sSuf = "}"

    [/autoit] [autoit][/autoit] [autoit]

    ; set the reset text
    _GUICtrlRichEdit_SetText( $hRichEdit, $sPre & $sText & $sSuf )
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _getMatches()
    ; first reset the RichEdit
    _reset()

    [/autoit] [autoit][/autoit] [autoit]

    ; read the RegEx input
    $sInput = GUICtrlRead( $iInput )
    If $sInput = "" Then Return

    [/autoit] [autoit][/autoit] [autoit]

    ; get a RegExRes (result)
    $aRegExRes = StringRegExp( $sText, $sInput, 3 )
    _ArrayDisplay( $aRegExRes ) ; ### debugging

    [/autoit] [autoit][/autoit] [autoit]

    ; do the replacing
    $iCount = UBound( $aRegExRes ) - 1
    If IsArray( $aRegExRes ) <> 0 Then
    For $i = 0 To $iCount Step 1
    $sRegEx = StringRegExpReplace( $sText, $sInput, '{\\b ' & $aRegExRes[$i] & '}', 1 )
    MsgBox( "", $i, $sPre & $sRegEx & $sSuf ) ; ### debugging
    _GUICtrlRichEdit_SetText( $hRichEdit, $sPre & $sRegEx & $sSuf )
    Next
    EndIf
    EndFunc
    #endregion

    [/autoit] [autoit][/autoit] [autoit][/autoit]


    Der Ausdruck [Tüx] bringt mir bspw. im Array $aRegExRes 7 Treffer. Jedoch wird immer die erste Stelle, der erste Treffer ersetzt. Dies eben mit den Varianten im Array. Nun möchte ich jedoch, dass bei 7 Treffern, auch 7 Stellen mit den richtigen Werten ersetzt werden. Warum die Treffer so nicht gleichmäßig ersetzt werden können, ist mir klar, aber mir fehlt die Lösungsstrategie. Ich weiß nicht, wie ich dies sinnvoll umsetzen könnte.

    Hinweis:
    Für das "highlighting" nutze ich die Eigenschaften des RichEdits bzw. von RTF. Dabei setze ich vor den Treffer eindach {\b und danach wieder } .

    Ich bin über jede Idee, Verbesserung oder einen Ansatz dankbar. In diesem Sinne, einen angenehmen Tag noch.

    UserIsGrateful 【ツ】

    Einmal editiert, zuletzt von Sven-Seyfert (4. April 2014 um 17:58)

  • Hallo und vielen Dank i2c ,

    nein nicht ganz, muss ich sagen. Ist zwar auch nicht schlecht, erfüllt aber nicht meine Anforderung. Ist auch nicht ganz so einfach, diese sinnvoll zu beschreiben muss ich zugeben.

    Jedoch nicht so schlimm, denn ich hab's glaube ich. Einfach im oben beschriebenen Quellcode folgendes ändern, dann sollte einleuchtend sein - wo ich eigentlich hin wollte ;) .

    Alte Variante:

    Spoiler anzeigen
    [autoit]


    ; get a RegExRes (result)
    $aRegExRes = StringRegExp( $sText, $sInput, 3 )
    _ArrayDisplay( $aRegExRes ) ; ### debugging

    [/autoit] [autoit][/autoit] [autoit]

    ; do the replacing
    $iCount = UBound( $aRegExRes ) - 1
    If IsArray( $aRegExRes ) <> 0 Then
    For $i = 0 To $iCount Step 1
    $sRegEx = StringRegExpReplace( $sText, $sInput, '{\\b ' & $aRegExRes[$i] & '}', 1 )
    MsgBox( "", $i, $sPre & $sRegEx & $sSuf ) ; ### debugging
    _GUICtrlRichEdit_SetText( $hRichEdit, $sPre & $sRegEx & $sSuf )
    Next
    EndIf

    [/autoit]


    Neue Variante:

    Spoiler anzeigen
    [autoit]


    ; get a RegExRes (result)
    $aRegExRes = StringRegExp( $sText, $sInput, 3 )
    $aRegExRes = _ArrayUnique( $aRegExRes )
    _ArrayDelete( $aRegExRes, 0 )
    _ArrayDisplay( $aRegExRes ) ; ### debugging

    [/autoit] [autoit][/autoit] [autoit]

    ; do the replacing
    $iCount = UBound( $aRegExRes ) - 1
    If IsArray( $aRegExRes ) <> 0 Then
    For $i = 0 To $iCount Step 1
    $sRegEx = StringReplace( $sText, $aRegExRes[$i], '{\b ' & $aRegExRes[$i] & '}', 0, 1 )
    $sText = $sRegEx
    _GUICtrlRichEdit_SetText( $hRichEdit, $sPre & $sRegEx & $sSuf )
    Next
    EndIf

    [/autoit]


    Ging mir so zu sagen um die Markierung der Treffer. Diese sollten einfach nur im Text hervorgehoben werden. Würde sie auch gern ROT darstellen, aber irgendwie bekomme ich das mit RTF nicht hin. Jedoch ist dies nicht so wichtig, denn FETT geht nun schonmal :D .

    Vielen Dank nochmals für die Unterstützung.

    UserIsGrateful 【ツ】