Wieder mal RegexReplace...

  • Hallo zusammen,
    ich habe zum Ersetzen von Werten in *.csv-Dateien ein Regex, welches auch den richtigen Treffer findet, s. ArrayDisplay().
    Wenn ich jetzt aber diesen Treffer ersetzen möchte, wird nicht nur der Treffer, sondern auch die "non capturing groups" ersetzt?!
    Was muss ich ändern, damit RegexReplace() nur den gematchten Teil ersetzt?

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

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

    $txt = @crlf
    For $i = 1 To 5
    For $r = 1 To 20
    $txt &= $i & $r&"|"
    Next
    $txt &= @CRLF
    Next
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $txt = ' & $txt & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

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

    $pattern = '(?m)34(?:[^\|]*\|){12}((?:[^\|]*\|{1}){3})' ;12 spalten nach dem treffer die drei folgenden spalten
    $res = StringRegExp($txt, $pattern,3)
    _ArrayDisplay($res) ;sollen ersetzt werden durch

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

    $res = StringRegExpReplace($txt, $pattern, "xxx|yyy|zzz|",1)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $res = ' & $res & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit]


    Es sollen die "316|317|318|" durch "xxx|yyy|zzz|" ersetzt werden.

    //EDIT, mit $res = StringRegExp($txt, $pattern,2) sehe ich im ArrayDisplay() den "falschen" Treffer im ersten Index, der richtige ist im zweiten...
    Wie bekomme ich es hin, dass der "richtige" String ersetzt wird?

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    2 Mal editiert, zuletzt von Andy (11. November 2014 um 21:31)

  • [autoit]


    #include <Array.au3>

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

    $txt = @crlf
    For $i = 1 To 5
    For $r = 1 To 20
    $txt &= $i & $r&"|"
    Next
    $txt &= @CRLF
    Next
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $txt = ' & $txt & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

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

    ;$pattern = '(?m)34(?:[^\|]*\|){12}((?:[^\|]*\|{1}){3})' ;12 spalten nach dem treffer die drei folgenden spalten

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

    $pattern = '(?m)(34(?:[^\|]*\|){12})((?:[^\|]*\|{1}){3})' ;weitere Klammern eingefügt

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

    $res = StringRegExpReplace($txt, $pattern, "\1xxx|yyy|zzz|",1); ein \1 vor den Text
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $res = ' & $res & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit]

    So sollte es klappen, ich habe den vorderen Teil des Pattern eingeklammert und bei dem String "xxx|yyy|zzz" ein "\1" vorgesetzt.
    Das \1 wird durch den Inhalt der ersten klammer ersetzt, so sollte das richtige Ergebnis rauskommen. :thumbup:

    mfg
    Zeitriss

  • Sehr nice, vielen Dank!

    Um das nachzuvollziehen wie RegexReplace arbeitet:
    Die mit \1 \2 \3 usw. im Replace bezeichnen die Ergebnisse der capturing groups des Regex. //EDIT Falsch!
    \1abcde ersetzt die erste capturing group durch abcde und \6xyz ersetzt die sechste capturing group durch xyz. //EDIT Auch falsch!

    Btw. die zusätzlichen Klammern sind nicht nötig :thumbup: Auch falsch!
    Richtig ist, dass es völliger Schwachfug ist, dass Regexp einen passenden String zurückgibt, aber das identische Pattern bei RegexpReplace ein anderes Ergebnis zurückgibt!
    So wie ich das sehe, hat das eine mit dem anderen nicht viel zu tun. Gut zu wissen...

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (11. November 2014 um 22:47)

    • Offizieller Beitrag

    Btw. die zusätzlichen Klammern sind nicht nötig


    Ähhm, doch. Replace ersetzt alles, was im Match ist, völlig egal ob in Capturing Groups oder nicht. Also alles, was dein Pattern erfasst, wird gnadenlos gegen Replace-String ersetzt. Somit muß das, was erhalten bleiben soll auch in Capturing Groups gefangen werden und über deren Nummer (entweder mit "$1" "$2" od. "\1" "\2" usw.) dem Replace-String beigefügt werden.

  • Ähhm nein! Wäre doch vollkommen unlogisch, wenn ALLE matches ersetzt würden, dann bräuchte man weder capturing, noch non capturing groups. Habe das jetzt auch mit anderen Strings ausprobiert, es werden immer nur die capturing groups ersetzt (mit backreference).
    Wenn KEINE backreference bspw. \1 im zu ersetzenden String gesetzt ist, dann stimmt deine Aussage! s. Arraydisplay im EDIT Post #1, das zeigt alle matches.

    //EDIT s.Post #3,

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (11. November 2014 um 22:48)

  • Ich weiß, dass StringRegExpReplace anders arbeitet als StringRegExp, wie es BugFix bereits gesagt hat. Man muss bei StringRegExpReplace anders, und in meinen Augen ist das schwieriger als StringRegExp, denken.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    • Offizieller Beitrag

    Vielleicht reden wir aneinander vorbei.
    Mir geht es um diese Klammern (denn nur durch diese erhältst du die Capturing Group 1 beginnend bei 34):
    '(?m)(34(?:[^\|]*\|){12})((?:[^\|]*\|{1}){3})'

    Match ist alles was das Pattern zusammenhängend findet. Somit kannst du ja n-Matches haben (deshalb gibt es das Flag für Anzahl Ersetzungen).
    Und Replace ersetzt immer ALLES was der Match repräsentiert. Glaub es oder probiere es aus. :P
    Deshalb die Capturing Groups, damit beim Replace nichts verloren geht und man nur das nötige ersetzt. ;)