SuchString zwischen den ersten und den letzten Buchstaben eines Satzes verwenden

  • Hallo,

    Ich möchte meine über 1.400 angesammelte Serverlog-Dateien (.txt von den letzten 4 Jahren) auswerten bzw. mit Hilfe von Tabellenkalkulation weiterbearbeiten und eine Statistik über bestimmte Einträge erstellen. Vorab ist aber ein großes Problem zu lösen, dass in ca. 2/3 der Dateien - Servereinträge -, also Zeilen enthalten sind, welche nicht mit ausgewertet werden dürfen. Dabei handelt es sich um andere Domains und Subdomains, die nicht zu meinem Auswertungsziel gehören.

    Was möchte ich:
    - Recursiv ein Verzeichnis einlesen mit allen Unterverzeichnissen und deren (.txt) Dateien mittels _FileListToArrayRec (ich hoffe dass das richtig ist)

    - In den .txt und .log Dateien nach Zeilen Suchen die mit "http://top-" beginnen und alle mit ".exe" und "bat" und "php" und "html" enden, entfernen. Das Problem ist also, dass ich die Such-Strings nicht mit einem gewöhnlichen StringReplace ersetzen kann, weil der Inhalt ja immer zwischen "http://top-" und ".exe" und "bat" und "php" und "html" unterschiedliche Inhalte hat. Auch die Zeilennummern sind bei diesen Serverlogs immer unterschiedlich.

    AutoIt
    ; Das hier würde zum Beispiel nicht funktionieren weil der Text "undderInhaltistimmerunterschiedlich" variiert.
    $file = fileopen("Log1.txt",2)
    $file2 = StringReplace($file,"http://undderInhaltistimmerunterschiedlich","")
    filewrite("Log000001.txt",$file2)


    Ich hoffe Ihr könnt verstehen was ich meine.

    Es wäre klasse, wenn mit bitte jemand bei einer Lösung helfen könnte. Ich weiß nicht wirklich, wie es sinnvoll zu lösen wäre.

  • Zeilenweise If StringInString("http://top-") dann..

    If StrinInString then StringReplace..
    oder wenn viele Dinge ausgeschlossen, werden, die in ein Array und dann _Arraysearch Not @error then StringReplace.

    Entweder verstehe ich dich falsch, oder es ist eigentlich ganz einfach.

    Grüße autoiter

  • Das schreit doch gerade zu nach regulären Ausdrücken. So kannst du alle irrelevanten Einträge in einem Datensatz mit einem Einzeiler entfernen. Das ist a) weniger aufwändig zu programmieren und b) vermutlich wesentlich schneller als eine Lösung mit X String-Befehlen.

    Konkret würde ich StringRegExpReplace verwenden und dann einfach alle irrelevanten Zeilen durch Leerstrings ersetzen. Ohne weitere Bastelei hat das nur den Nachteil, dass die letzte Zeile zu einer Leerzeile wird, falls sie entfernt wird.

    [autoit]


    $sLogTestData = "http://top-test.de/myfile.exe" & @CRLF & _
    "http://nottop-test.de/myfile.exe" & @CRLF & _
    "http://top-test.de/index.php" & @CRLF & _
    "http://top-test.de/myfile.sh" & @CRLF & _
    "http://top-test.de/index.html"
    ;Zeile 1, 3 und 5 müssten entfernt werden

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

    MsgBox(0, "Vorher", "---" & @CRLF & $sLogTestData & @CRLF & "---")
    $sLogTestData = StringRegExpReplace($sLogTestData, "(?m)^\Qhttp://top-\E.*?(?:\.exe|\.bat|\.php|\.html)$(\r\n)?", "")
    MsgBox(0, "Nachher", "---" & @CRLF & $sLogTestData & @CRLF & "---")

    [/autoit]
  • oder wenn viele Dinge ausgeschlossen, werden, die in ein Array

    Das möchte ich ja umgehen.

    Es soll die Zeile die mit "http://top-" beginnt und mit z.b. "32" oder "exe" endet, gelöscht werden bzw. mit "blanks" aufgefüllt werden.


    Konkret würde ich StringRegExpReplace verwenden und dann einfach alle irrelevanten Zeilen durch Leerstrings ersetzen.

    Vielen Dank für Dein Beispiel. Beispiele sind immer das beste was mir passieren kann. Aber ich blicke nicht was Du meinst. Mit Deinem Beispiel benötige ich ja ein vordefiniertes Ziel wie z. B. "$sLogTestData = "http://top-test.de/myfile.exe". Und alles was dann nicht dem "pattern" -von-bis entspricht, wird rausgehauen. Jedoch verstehe ich nicht, wie mir das helfen kann. Ich verstehe Dein Beispiel anhand der MsgBox, aber anhand meiner Logdatei mit ca. 400 Zeilen kapiere ich das nicht mehr. Bitte helfe mir auf die Sprünge.

    PS.: ist die Endung der Zeile eigentlich egal? Oder kann ich das Ende besser gesagt auch undefiniert lassen? Ich habe auch Logdateien, welche die Ausgabe eines Arrays zeigen. Also so etwa:

    Code
    http://www.top-test.de/bla/blup/dev/Multi7/Basic/test.srt;541


    Das ;541 steht für die Downloadanzahl der Datei. Also wie gesagt habe ich mehrere Hundert Zeilen pro Datei und ich möchte wie im Code gezeigt, die Ganze Zeile löschen. Event. auch nur wenn die Zeile mit "http://www.top-" beginnt und ich gar nicht angeben kann, was am Schluss steht.

  • @bazii

    - In den .txt und .log Dateien nach Zeilen Suchen die mit "http://top-" beginnen und alle mit ".exe" und "bat" und "php" und "html" enden, entfernen.

    Du hattest eigentlich ganz klar von Zeilen gesprochen, die aud .exe, bat, php und html enden.
    Nun passt die Lösung nicht auf einen ganz anderen Fall...

    Da ich keine elegante Lösung wie @chesstiger präsentieren kann, würde ich bei String-Operationen nun vorschlagen das letzte Semikolon und Anhang zu entfernen und dann auf eine nicht gewünschte Endung zu prüfen.

    Aber ist das dann auch wirklich die Lösung, oder hast du noch ganz andere Fälle?

    Grüße autoiter

    • Offizieller Beitrag

    @bazii Ich würde sagen: Klassisches UND-ODER Problem.

    So wie du es beschrieben hast, bist du vom umgangssprachlichen UND ausgegangen. Das ist programmiertechnisch aber ein ODER!
    Bsp.:
    Ein Geschäft hat geöffnet: Mo und Freitag von 10-12 Uhr
    Programmabfrage, wann ist die Bedingung OFFEN wahr? - wenn: "Mo (10-12)" ODER "Fr (10-12)"

    Darum bei Fragestellungen bitte genau auf die Bedingungen achten. :rolleyes:

  • Jedoch verstehe ich nicht, wie mir das helfen kann. Ich verstehe Dein Beispiel anhand der MsgBox, aber anhand meiner Logdatei mit ca. 400 Zeilen kapiere ich das nicht mehr. Bitte helfe mir auf die Sprünge.

    Ganz einfach. Es ist egal, was $sLogTestData beinhaltet. Ich habe im obigen Beispiel einfach mal angenommen, dass wir eine Testdatei mit 5 Zeilen haben. Ob diese X Zeilen jetzt aus einer wirklichen Datei mittels FileRead() kommen oder ob ich das zu Testzwecken direkt im Skript notiere... Ist ja im Prinzip egal. Das ist eins zu eins austauschbar. Diese Variable beinhaltet einfach den gesamten Text, nicht nur eine Zeile. Statt der MsgBox kommt dann halt bei dir am Ende ein FileWrite, sodass du die Daten weiterverarbeiten kannst.

    Und was dein P.S. angeht... Mit regulären Ausdrücken kann man auch das deichseln. Bezieht sich diese Zahl am Ende auf alle Dateiendungen oder nur auf die o.g. Dateiendungen?

  • Hallo,

    ich danke Euch allen für die Rückmeldungen und möchte mich bei Euch entschuldigen, wenn ich einen unklaren Eingangspost geschrieben habe. Es ist für mich aber auch nicht ganz einfach zu erklären was ich möchte. Daher versuche ich nochmal neu, meine Anforderungen an das Script zu definieren. Ihr würdet sicher meine Anforderungen in einem Satz definieren. Ich benötige dafür eine A4 Seite X/

    Meine Logdateien sind pro Datei mit mehreren 100 Einträgen vollgestopft mit Zeilen wie in folgendem Codefenster beispielhaft zu sehen ist:

    Die Endungen sind immer unterschiedlich.

    Was ich möchte ist, dass alle Zeilen gelöscht werden, die das Wort top- enthalten. Die Zeilen-Endung ist daher jetzt erstmal nicht wichtig.

    @BugFix & @autoiter & @chesstiger: Euer Posting trifft bei jedem von Euch den Nagel voll auf den Kopf. Für einen Gärtner wie mich, ist die Definition von "Werkzeug" - der "Spaten&|Schaufel&|Rechen&|Besen". Beim programmieren (unähnlich gärtnern) habe ich das Gegenstück zu "&", dann also "oder", einfach nicht in meinen Gehirnwindungen verankert, wie so manches andere auch nicht was zum coden nötig wäre. Daher brauche ich immer wieder mal jemanden wie Euch, der mir auf die Sprünge hilft. So macht es mir Spass zu lernen oder besser gesagt zu lesen (denn kapieren kann ich nicht alles), was Ihr in Euren Postings und im Code alles berücksichtigt.

    So also ist für mich diese Zeile "(?m)^\Qhttp://top-\E.*?(?:\.exe|\.bat|\.php|\.html)$(\r\n)?", ""), selbst dann, wenn ich die Hilfe dazu betrachte ein Zeile, welche eine gewisse Voraussetzng erfordert, die ich nicht erfüllen kann. Was bedeutet z. B. aus der Zeile von StringRegExpReplaceheraus die Zeichenfolge (?m)^ oder \E.*?(?:. Dennoch habe ich bei einfachen Dingen sehr viel Spass an Autoit und bin auch schon bei einigen kleinen Skripten sehr stolz darauf, Mit Hilfe von Euch und allerhand Beispielskripten etwas hinbekommen zu haben.

    Vielen Dank nochmal für Eure Hilfe.

  • Klappt einwandfrei.

    AutoIt
    $hfileout = (@ScriptDir & "\01_2013_.txt")
    $hfile = FileRead(@ScriptDir & '\01_2013.txt')
    $hfile = StringRegExpReplace($hfile, 'http:\/\/www\.top-.+?\R', '')
    FileOpen($hfileout, 2)
    FileWrite($hfileout, $hfile)
    FileClose($hfileout)


    Jedoch bin ich trotzallem sehr neugierig, wie Du (oder auch @chesstiger) die Zeichenfolgen unter StringRegExpReplacezusammengesetzt hast. Gibt es dazu ein Nachschlagewerk oder ähnliches? Oha! Ich habe über die Hilfe und über einen weitergehenden Link von [url='../tutorials/regexp/regexp.htm']Regular Expression[/url] den Hinweis auf diese Internetseite gefunden. The 30 Minute Regex Tutorial. Das werde ich mal am Wochenende studieren (wobei ich dadurch wahrscheinlich leider nicht schlauer oder ein besserer Programmierer werde :Face: ) Da steht z. B. unter +? "Repeat one or more times, but as few as possible" / Auf Google sagt mir das folgendes: "Wiederholen Sie ein oder mehrere Male, aber so wenig wie möglich" ----Wer außer Ihr kapiert denn so was und weiß auch noch, dass und wie und wo man das im Code einfügen muss?

    Mann oh Mann was habt ihr in den "Schoppen" bekommen, dass ihr sowas versteht? Na ja, um ehrlich zu sein gibt es da ein altes Sprichwort:

    Zitat von Gärtner

    Der eine hats, der andere nicht
    und wer's nicht hat, bekommts auch nicht
    auch dann nicht, wenn er es mit Löffeln frist.


    ;( Alte Gärtnerregel übrigens.

    Vielen Dank Euch allen für die Hilfe.

  • RegExp nur stumpf nach Tutorial zu lernen ist meist nicht mit allzu viel Erfolg verbunden. Das muss man einfach machen. Dann wird man mit der Zeit immer geschickter.
    Die AutoIt-Hilfe ist eigentlich schon ein guter Anlaufpunkt im Sinne eines Nachschlagwerkes, bei StringRegExp steht eigentlich alles übersichtlich erklärt. Man muss nur einmal das Grundprinzip der regulären Ausdrücke verstanden haben.
    Auf die Gefahr hin, dich noch mehr zu verwirren... Will ich das mal kurz umreißen:

    Erstmal gilt es zu klären, was ein regulärer Ausdruck ist. Im Prinzip beschreibt so ein Ausdruck nur ein gewisses Muster, dem ein Eingabetext folgen muss. In "Pseudocode" könnte ich zum Beispiel bei dem Eingabetext Meine Zahl ist 42, der Sinn des Lebens. sagen: Ich suche zwei Ziffern (von 0 bis 9) hintereinander. Dann wäre das Ergebnis 42. Ich beschreibe also die textliche Form und Umgebung, in der meine gesuchte Information vorliegt und wende dieses allgemeine Muster dann an, um an meine konkrete Information zu gelangen. Mal kurz drüber nachdenken, vielleicht nochmal lesen. Dann sollte es Sinn machen. Normalerweise sollte der Grundgedanke von RegExp dir helfen.

    Dann will ich dir auch noch kurz meinen komplizierten Ausdruck von oben grob erklären.

    Spoiler anzeigen


    (?m) - Das nennt man eine Option. Konkret sorgt m (für multiline) dafür, dass ^ und $ nicht nur Anfang und Ende des gesamten Textes darstellen, sondern auch Zeilenanfang und -ende.
    ^ - Text- oder Zeilenbeginn.
    \Qhttp://top-\E - \Q ... \E bewirken einfach nur, dass der Text dazwischen nicht als RegExp-Befehl interpretiert wird. \Q^\E würde beispielsweise keinen Zeilenanfang darstellen, sondern das Zeichen "^" an sich.
    .*? - Der Punkt bedeutet "Ein beliebiges Zeichen (bis auf Zeilenumbruch)". Das Sternchen bedeutet "beliebig oft". Das Fragezeichen bedeutet "nicht mehr als unbedingt nötig". .* alleine bedeutet also einfach "Beliebig oft ein beliebiges Zeichen" und dient als Universalplatzhalter. Das Fragezeichen ist schon ein wenig komplizierter. Beim regulären Ausdruck A.*C würde bei dem Eingabetext "ACDC" auch "ACDC" gematcht. Ohne Fragezeichen wird also .* als so lang wie möglich angenommen, das hintere C wird verwendet. Bei A.*?C wäre das Ergebnis so kurz wie möglich, also "AC", eben weil das erste C verwendet wird. Ein wenig holprig erklärt, gebe ich zu.
    (?: - Eine sogenannte "Non-Capturing Group". Liest sich wie eine normale Klammer in der Mathematik. Der aussenstehende Operator wird auf alles zwischen (?: und ) angewendet.
    \.exe|\.bat|\.php|\.html - Der Backslash dient zum Maskieren, im Prinzip die Kurzform von \Q...\E. Es wird also nicht ein beliebiges Zeichen gesucht, sondern der Punkt. Der Querstrich bedeutet einfach "Oder".
    ) - Ende der Gruppe (von "(?:").
    $ - Zeilen- oder Textende.
    (\r\n)? - \r\n ist ein Zeilenumbruch unter Windows. Wenn das Fragezeichen ohne einen Stern oder ein Plus da steht, dann liest es sich als "Einmal oder keinmal".

    RegExp zu lernen ist anstrengend. Aber es lohnt sich, glaub mir. Das ist extrem nützlich, nicht nur in AutoIt. ^^

  • Somit wird da wird schon vieles deutlicher und klarer. Es gibt mit RegExp dermaßen viele Möglichkeiten. Das zu lernen lohnt sich bestimmt. Vielen Dank für die klasse Erklärungen und für die sehr gute Hilfe.