Strings aus Textdatei entfernen

  • Hey Leute,
    ich komme mit der Bearbeitung von meinen Textdateien nicht weiter. Ich habe zwei Textdateien, die ich zeilenweise auslesen will und dann bestimmte Teile zusammenführen möchte. Einen anderen Teil möchte ich in ein anderes Dokument speichern. So weit so gut..
    Die eine Liste ist ganz easy, erst immer die gleiche Anzahl Zeichen. Ich will einmal alles nach dem ersten Leerzeichen und dann die letzten 4 Zeichen vor dem Leerzeichen. Das klappt wunderbar mit StringLeft und StringMid.

    o86400017859 MEINE INFOS
    b754kw017611 MEINE INFOS DIE ICH
    8a1a0001c552 MEI FOS HABEN
    86a00k017858 HABEN WILL

    Wie man an die zweite Liste herangeht weiß ich aber nicht. Sieht wirr aus, aber das Muster ist Zeichenfolge gefolgt von Leerzeichen, gefolgt von Zeichenfolge, gefolgt von Leerzeichen, gefolgt von dem Text den ich haben will. Dabei sind alle Teile des Textes unterschiedlich lang.

    Mit StringSplit (Leerzeichen als Trenner) kam ich nicht vorwärts, oder kann man alle Variablen Werte übernehmen AUßER [1] [2]?

    Wie lösche ich den je Zeile den Text mitsamt des zweiten Leerzeichens?

    20eb271ef059 281895470 DIE DATEN DIE ICH HABEN WILL
    236b271df001c 22832167147897 DIE ICH HABEN WILL
    5ceb263 281670250733005583 DIE DATE
    61eb000d074 3659745509077 DIE ICH HABEN
    1eb000d0085006 3659745935115255 DATEN DIE ICH HABEN WILL

    Danke für eure Aufmerksamkeit und hoffe jemand kann mir da helfen. Falls ich noch Fragen beantworten muss, kann ich das aber leider erst morgen machen.
    Grüße

    Grüße autoiter

    Einmal editiert, zuletzt von autoiter (18. März 2014 um 00:08)

  • [autoit]

    Mit StringSplit (Leerzeichen als Trenner) kam ich nicht vorwärts, oder kann man alle Variablen Werte übernehmen AUßER [1] [2]?

    [/autoit]


    Ja, mit simpler Logik:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>

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

    $aData = StringSplit(ClipGet(), @CRLF, 1) ;Anstatt dieser Zeile würdest du FileReadToArray nutzen
    ; ^ Einfach nur ein Array mit einer Zeile in jedem Element (und der Anzahl in [0]) ^

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

    _ArrayDisplay($aData, "Vor dem Bereinigen") ;Einmal vorher roh anzeigen

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

    For $i = 1 To $aData[0]
    $aTemp = StringSplit($aData[$i], " ") ;Die Zeile nach Leerzeichen splitten (=> Teilzeilenarray)
    $aData[$i] = "" ;Die Originaldaten im Hauptarray leeren
    For $j = 1 To $aTemp[0]
    If $j <= 2 Then ContinueLoop ;Das Teilzeilenarray ab Element [3] bearbeiten (0, 1 und 2 werden übersprungen)
    $aData[$i] &= $aTemp[$j] & " " ;Die in Z. 10 geleerte Originalzeile nach und nach wieder befüllen
    Next
    $aData[$i] = StringTrimRight($aData[$i], " ") ;Das letzte Leerzeichen aus Z. 13 wieder entfernen
    Next

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

    _ArrayDisplay($aData, "Nach dem Bereinigen") ;Nochmal anzeigen

    [/autoit]


    Da es ein kurzes Beispiel ist, wird vorausgesetzt, dass sich die Beispieldaten aus deinem Post in der Zwischenablage befinden.

    Gruß

  • Moin!
    Hier mal mein Vorschlag mit RegEx. Ist deutlich kürzer und weniger aufwendig (zumindest wenn man reguläre Ausdrücke mal verstanden hat) 8)

    Auch hier wird vorausgesetzt, dass sich die Beispieldaten in der Zwischenablage befinden:

    [autoit]

    #include <Array.au3>

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

    $sData = ClipGet()
    MsgBox(0, "Rohdaten", $sData)

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

    ;==> Filtern des ersten Beispieldatenblocks (löscht alles bis nach dem ERSTEN Leerzeichen, bzw kopiert alles nach dem ERSTEN Leerzeichen in ein Array)
    ;$aData = StringRegExp($sData, ".+? (.+)", 3); Dieser Pattern geht auch: ".*? (.*)"
    ;_ArrayDisplay($aData)

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

    ;==> Filtern des zweiten Beispieldatenblocks (löscht alles bis nach dem ZWEITEN Leerzeichen, bzw kopiert alles nach dem ZWEITEN Leerzeichen in ein Array)
    $aData = StringRegExp($sData, ".+? .+? (.+)", 3); Dieser Pattern geht auch: ".*? .*? (.*)"
    _ArrayDisplay($aData)

    [/autoit]


    Hier findest du ein RegEx Tutorial, falls du dich weiterbilden willst... :rolleyes:

  • Danke euch für die Hilfe. Leider war ich jetzt ständig mit anderen Sachen beschäftigt und habe nur den Code von chesstiger ausprobiert. Funzt. Aber boah, ich steh sowas vom an Anfang. Ich hab mich erstmal gewundert wo FileReadToArray zu finden ist. In der Funktionsreferenz war es nicht zu finden. Aber Aha! Es gibt auch userdefined Functions :D
    Ich setze mich heute Abend ausführlich damit auseinander und wollte nur mal melden, dass eure Hilfe nicht ins Nirvana gegangen ist.

    Friesel
    Ja, Hammer wie kurz der Code ist und danke für den Tutorial Link. Lustigerweise hatte ich den Link auch schon in der Shoutbox bekommen und aufgerufen, später aber geschlossen und nicht wiedergefunden.. Das schaue ich mir auf jeden Fall an.

    Grüße

    Grüße autoiter

  • Ah, danke. Ich hab mal ein Update gemacht NewVersionTester.

    Friesel
    Ich kam noch nicht zum Tut. Das werde ich noch machen. Aber es kam mir zu viel dazwischen. Meist habe ich mit Texten zu tun und über kurz oder lang möchte ich die auch beherrschen. Deinen Code konnte ich allerdings nicht einfach anwenden. Das klappt nicht. Siehst du den Fehler?

    [autoit]


    Dim $Data
    _FileReadToArray(@AppDataDir & "\Testprojekt\Test.txt",$Data)

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

    _ArrayDisplay($Data, "Vor dem Bereinigen") ;Einmal vorher roh anzeigen

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

    $bData= StringRegExp($Data, ".+? .+? (.+)", 3) ; Ab hier geht nix mehr..

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

    _ArrayDisplay($bData, "Nach dem Bereinigen") ;Nochmal anzeigen ------- Es kommt nie zu dieser zweiten Darstellung.
    _ArrayDelete($bData, 0)
    _FileWriteFromArray(@AppDataDir & "\Testprojekt\Test.txt", $bData)

    [/autoit]

    Mit chesstigers Weg konnte ich mein Problem schon lösen. Allerdings lasse ich den Thread erst einmal noch offen, weil ich vielleicht neue Fragen klären kann.

    Grüße autoiter

    Grüße autoiter

  • Moin!

    Meine Methode verarbeitet den kompletten Text in einem und nicht, so wie du es versuchst, zeilenweise.
    Man könnte es zwar auch zeilenweise abarbeiten, was aber viel zu umständlich wäre.

    In deinem Skript greift StringRegExp auf die Variable $Data zu, die aber ohne Inhalt ist. Die Daten sind in diesem Fall in $Data[1], $Data[2] usw gespeichert.

    Du mußt also einfach den Inhalt der Datei in eine einzige Variable einlesen ($sData) und diese an StringRegExp übergeben.

    Und so einfach gehts:

    [autoit]

    #include <File.au3>
    #include <Array.au3>

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

    $sData = FileRead("Test.txt");==> "Test.txt" befindet sich im Skriptverzeichnis. Den Pfad mußt du noch anpassen.

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

    ;==> Alternative für große Dateien (siehe Hilfe zu "FileRead")
    ;$hData = FileOpen("Test.txt", 0)
    ;$sData = FileRead($hData)
    ;~~~
    ;FileClose($hData) ==> FileClose, wenn die Bearbeitung der Daten beendet ist (bzw nach dem letzten "FileRead($hHandle)")
    ;<==

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

    MsgBox(0, "Rohdaten", $sData)
    $aData = StringRegExp($sData, ".+? .+? (.+)", 3)
    _ArrayDisplay($aData)
    _FileWriteFromArray("Test1.txt", $aData);==> Datei in "Test.txt" umbenennen, falls du keinen Wert auf eine Sicherheitskopie der Orginaldaten legst

    [/autoit]

    Sanfte Grüße :)

  • Nur um auch mal einen Vorschlag einzuwerfen - ein Einzeiler (sollte auch die schnellste Methode sein):

    [autoit]

    FileWrite(FileOpen("Test2.txt", 2), StringRegExpReplace(FileRead("Test.txt"), "(?m)^(\S++ \S++ )", ""))

    [/autoit]


    (FileClose wird ausnahmsweise mal nicht benötigt, da das Skript sowieso gleich beendet wird und damit auch das Handle stirbt)

    autoiter
    Was NewVersionTester dir sagen wollte war: Es gibt mittlerweile zwei Versionen der _FileReadToArray()-Funktion.
    Eine mit Unterstrich und eine ohne. Die mit Unterstrich ist eine UDF - also in ("langsamen") AutoIt-Code geschrieben.
    Die neue ohne Unterstrich ist in AutoIt eingebaut. Liegt also in Maschinencode vor und sollte daher schneller sein.
    Man sollte daher wenn man nicht Rückwärtskompatibilität benötigt die Version ohne Unterstrich verwenden.

    3 Mal editiert, zuletzt von AspirinJunkie (6. März 2014 um 08:57)

  • Danke Leute,
    ich finds phänomenal, wie kurz man den Code halten kann (wenn man sich richtig auskennt). Ich habe mittlerweile einen riesigen Codehaufen, der wahrscheinlich zur Hälfte unnötig ist :D
    @ AspirinJunkie
    Danke für die Erklärung. Mir war der Unterschied bisher nicht klar.

    Grüße autoiter

    Grüße autoiter

  • Nun habe ich doch noch eine Frage, die nicht gleich ist, aber sich doch auf diese Texte bezieht.


    Ich lade eine Liste mit InetGet herunter, die ich dann bearbeite. Es ginge ja auch mit InetRead. Ich weiß aber nicht, was besser ist. Wenn ich nun eine lange Liste habe und nur die ersten 100 oder 200 Zeilen brauche, wäre es am sinnvollsten, ich speicherte nur diese Anzahl Zeilen, oder kürze den vorhandenen Text. Danach wären weitere Schritte schneller.


    Wie macht man das?


    War dumm. Bitte vergesst das.. ;)

    Grüße autoiter

    Einmal editiert, zuletzt von autoiter (2. April 2014 um 12:24)