RegEx und Arrays

  • Hallo zusammen,


    ich bin seit einiger Zeit am Verzweifeln.

    Ich versuche gerade ein kleines Tool zu schreiben, das folgende Aufgabe erfüllen soll.

    Ich habe eine txt Datei, in der eine unbekannte Anzahl an Zeilen sind. Die Zeilen beginnen immer mit drei Zahlen, danach folgen 4 Ziffern gefolgt von einem Text.

    Ziel ist es, aus der Datei alle Texte aus den Zeilen die mit XXX6228 beginnen auszulesen. In jeder Quelldatei ist mindestens eine solche Zeile vorhanden. Maximal sind diese nicht begrenzt.

    Die Texte sollen mit einem Komma als Trennzeichen in eine neue Datei kopiert werden.

    Hinter meinem (Lösungs)Ansatz steckt folgende Logik:

    Die Quelldatei in ein Array einlesen-->Das Array Zeile für Zeile überprüfen und zutreffende Ergebnisse in die Zieldatei schreiben.

    Momentan habe ich das problem das der Reguläre Ausdruck nicht das was ich Suche zurück gibt.

    Hier mal der Entsprechende Quellcode:

    [autoit]

    #include

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

    #include

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

    $tmp=""

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

    $exit=0

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

    _FileReadToArray("C:\test\quelle.txt",$tmp)

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

    ;_FileWriteFromArray("C:\test\Gelesen.txt",$tmp,0)

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

    $groese = $tmp[0]

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

    While $groese>0

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

    $test=$tmp[$groese]

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

    $erg = StringRegExp($test,"(?<=\d\d\d6228).+",3)

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

    $groese = $groese-1

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

    WEnd

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

    _ArrayDisplay($erg)

    [/autoit]


    Kann mir irgendwer verraten was ich falsch mache?

    Einmal editiert, zuletzt von CrazyCrac (13. Juli 2012 um 14:17)

    • Offizieller Beitrag

    1.mal wären Beispielsdaten von Vorteil.
    2. Dein StringRegExp liefert nur bei Erfolg ein Array zurück, dein _ArrayDisplay wird erst nach der Schleife aufgerufen.
    Somit wird, wenn überhaupt, nur das letzte StringRegExp Ergebnis angezeigt. Wenn StringRegExp fehlschlägt ist auch kein Array mer da.

  • Hallo zusammen,

    @raupy
    zu 1.
    eine Beispieldatei könnte wie folgt aussehen.

    Code
    4851111Uninteresanter Text
    8792242Text der auch nicht Interesant ist
    9871235Text den ich auch nicht brauche
    5586228Der Text den ich will
    0156228Noch einen Text den ich will

    zu 2.
    in der Schleife war so natürlich ein Fehler.
    Ich habe die Schleife nun leicht angepasst, und das Array $erg vorangehend deklariert.

    [autoit]

    While $groese>0
    $test=$tmp[$groese]
    $erg[0] = $erg[0] & StringRegExp($test,"(?<=\d\d\d6228).+",3)
    $groese = $groese-1
    WEnd

    [/autoit]

    Nun sollte doch meiner Logik nach aus dem ersten Feld des Arrays $tmp der höchste Index ausgelesen und in $groese geschrieben werden. (z.B. 5)
    danach wird geprüft ob $groese größer als 0 ist. Dies trifft beim ersten druchgang zu.
    Also wird der Wert aus $tmp beim Index $groese in $test geschrieben.
    danach wird der String mit dem Ausdruck verglichen, falls dieser Zutrifft wird das Ergebnis mit dem bisherigen Inhalt von $erg in das Array geschrieben?
    Was aber passiert ist, dass für jeden Durchgang eine 1 in das Array geschrieben wird...

    Gewollt wäre das jeweils NUR der Text in das Array geschrieben wird, wenn der RegEx eine Übereinstimmung findet.
    Wenn noch irgendwelche Infos fehlen, einfach Bescheid geben.

    $var
    Beide Patterns führen zum selben Ergebnis

    Einmal editiert, zuletzt von CrazyCrac (10. Juli 2012 um 09:11)

  • Du musst die Datei nicht zeilenweise durchgehen um StringRegEx zu verwenden.
    Kannst auch direkt ein Pattern auf die ganze Datei loslassen.
    Mal als Beispiel:

    Spoiler anzeigen
    [autoit]

    Global $s_FilePath = "file.txt"
    Global $s_File = FileRead($s_FilePath)

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

    Global $s_Pattern = "(?m)^\d{3}6228(.+)$"

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

    Global $s_OutText = ""

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

    For $i in StringRegExp($s_File, $s_Pattern, 3)
    $s_OutText &= $i
    Next

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

    MsgBox(0,"", "Text der an die Datei angefügt werden soll (Inhalt von $s_OutText): " & @CRLF & @CRLF & $s_OutText)

    [/autoit]


    Prinzipiell: Statt While und dem manuellen dekrementieren von $groese solltest du dir mal die For-Schleife anschauen.
    Ansonsten weist du deiner Variable $erg den Rückgabewert von StringRegExp zu - also ein Array da du ja als 3. Parameter für StringRegExp eine 3 eingetragen hast.
    Durch das & wird dieses Array implizit in einen String gewandelt - ich glaube kaum das es das ist was du möchtest.

  • Na dann gehen wir halt einfach mal einzeln durch um zu sehen was das Skript macht:

    [autoit]

    Global $s_FilePath = "file.txt"
    Global $s_File = FileRead($s_FilePath)

    [/autoit]

    Lese den Inhalt der Datei "file.txt" als String in die Variable $s_File.

    [autoit]

    Global $s_Pattern = "(?m)^\d{3}6228(.+)$"

    [/autoit]

    Das ist unser RegEx-Pattern mit dem wir deine benötigten Daten ausfiltern. Prinzipiell muss man sich ein bisschen in Reguläre Ausdrücke einlesen (z.B. >>hier<<). Dennoch hier mal ein paar kleine Einzelheiten aus dem Pattern:

    • (?m) - sorgt dafür dass mit "^" ein Zeilenanfang und mit "$" ein Zeilenende gefunden werden können.
    • \d{3} - Einfach nur eine Folge aus 3 beliebigen Zahlen
    • () - eine Gruppierung mit der man angibt dass die darin enthaltenen Zeichen als Fund der Funktion StringRegExp zurückgegeben werden sollen
    • .+ - eine beliebig lange (mindestens 1 Zeichen lang) Folge von beliebigen Zeichen außer Zeilenumbrüche
    [autoit]

    Global $s_OutText = ""

    [/autoit]

    Unsere Rückgabevariable. Diese wird als Leerstring vorbelegt damit unsere Ergebnisse später einzeln per &-Operator an diese angefügt werden können.

    [autoit]

    For $i in StringRegExp($s_File, $s_Pattern, 3)
    $s_OutText &= $i
    Next

    [/autoit]

    Hiermit wird unser Pattern auf den Inhalt in $s_File losgelassen, die Funde als Array zurückgegeben und das Array direkt einzeln durchgegangen. Per $s_OutText &= $i wird jeder einzelne Fund an unsere Ausgabevariable angefügt.
    Um diese Syntax vielleicht etwas besser zu verstehen schreibe ich es hier nochmal auf die etwas längere klassische Weise hin welche aber prinzipiell das Selbe macht:

    [autoit]

    Global $a_RegExArray = StringRegExp($s_File, $s_Pattern, 3)

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

    For $x = 0 To UBound($a_RegExArray)-1
    $s_OutText = $s_OutText & $a_RegExArray[$x]
    Next

    [/autoit]