Zum Inhalt wechseln


Foto

Letzte Zeile einer Textdatei auslesen...


  • Bitte melde dich an um zu Antworten
14 Antworten in diesem Thema

#1 BNils

BNils

    Newbie

  • 15 Beiträge

 

Geschrieben 12. Januar 2010 - 11:20

Hallo,

ein schönes Forum habt ihr hier :)

Ich habe ein Problem und zwar möchte ich aus einer textdatei (endung .log) nur die letzte Zeile auslesen und in dieser Zeile nach einem Wort suchen (z.B. quit).

Wie kann ich das anstellen?

Gruß Nils

#2 NilsK

NilsK

    Expert Member

  • 12.347 Beiträge

 

Geschrieben 12. Januar 2010 - 11:27

Moin,

etwas mehr Informationen benötigen wir schon: Was ist das Ziel des Ganzen? Von welcher Scripting-Sprache/-Umgebung reden wir? Geht es um eine neue Lösung oder willst du etwas Bestehendes erweitern? Geht es um eine einmalige oder eine wiederhiolte Aufgabe? Welchen Umfang hat die Logdatei? usw. usf.

Gruß, Nils

Nils Kaczenski

MVP Cloud and Datacenter Management
... der beste Schritt zur Problemlösung: Anforderungen definieren!

Kostenlosen Support gibt es nur im Forum, nicht privat!


#3 BNils

BNils

    Newbie

  • 15 Beiträge

 

Geschrieben 12. Januar 2010 - 11:41

Okay, das habe ich vergessen :)

Also es geht um die Windows PowerShell.

Die Log file kann mehr als 80.000 Zeilen haben, je nach dem wann der Fehler auftritt.

Im Moment Prüfe ich immer ob der Service Status auf Running steht und wenn nicht starte ich ihn.

Manchmal passiert es aber, das der Service auf Running steht, aber durch ein Fehler der Service nicht mehr richtig arbeitet, in dem Fall taucht in einer Zeile ein quit auf. Danach passiert dann ncihts mehr in der log.

Und in dem Fall möchte ich den service halt neustarten.

Gruß Nils

EDIT: Das einzige was mir so einviel, war mit folgendem Code die Zeilen zu zählen... aber das dauert eigentlich etwas zu lange... desshalb habe ich den ansatz nicht weiter verfolgt.

function getZeile ($zeile) {
  $datei = Get-content "C:\Program Files\Service1\service.log"
  $a = 0
  $datei | Foreach-Object { $a++}
  
  return $a
}


#4 BNils

BNils

    Newbie

  • 15 Beiträge

 

Geschrieben 13. Januar 2010 - 12:15

kann mir keiner helfen?

Gruß Nils

#5 phoenixcp

phoenixcp

    Expert Member

  • 5.481 Beiträge

 

Geschrieben 13. Januar 2010 - 12:32

Lass den Leuten mal ein wenig Zeit. Drängeln hat noch keinem geholfen und man macht sich auch nicht unbedingt beliebt damit. ;)
MfG

Carsten Paul
MCSEBoard.de SQL Blog
Kein Support per PN, dafür ist das Forum da!

In Memory of LukasB

#6 NilsK

NilsK

    Expert Member

  • 12.347 Beiträge

 

Geschrieben 13. Januar 2010 - 12:38

Moin,

ich habe keine vollständige Lösung, nur den Tipp es mal mit dem Log Parser zu versuchen. Der kann einige Dinge sehr effizient.

Kostenloser Download bei Microsoft.

Gruß, Nils

Nils Kaczenski

MVP Cloud and Datacenter Management
... der beste Schritt zur Problemlösung: Anforderungen definieren!

Kostenlosen Support gibt es nur im Forum, nicht privat!


#7 BNils

BNils

    Newbie

  • 15 Beiträge

 

Geschrieben 13. Januar 2010 - 12:43

Schade, aber vielleicht ja jemand anders...

Den LogParser schaue ich mir mal an

Danke

EDIT: Habe die Lösung gefunden, um nur die letzte Zeile auszulesen (überspringt leere Zeilen):

Get-Content c:\scripts\test.log | Select-Object -last 1

Bearbeitet von BNils, 13. Januar 2010 - 13:01.


#8 Dukel

Dukel

    Board Veteran

  • 9.259 Beiträge

 

Geschrieben 13. Januar 2010 - 13:05

if ((Get-Content file.log | Select-Object -Last 1) -match "quit"){
#Your Code here
}

Oder

...
(get-Content file.log)[(get-Content file.log).count-1]
...


#9 Dukel

Dukel

    Board Veteran

  • 9.259 Beiträge

 

Geschrieben 13. Januar 2010 - 13:07

Off-Topic:

[...]
EDIT: Das einzige was mir so einviel, war mit folgendem Code die Zeilen zu zählen... aber das dauert eigentlich etwas zu lange... desshalb habe ich den ansatz nicht weiter verfolgt.

function getZeile ($zeile) {
  $datei = Get-content "C:\Program Files\Service1\service.log"
  $a = 0
  $datei | Foreach-Object { $a++}
  
  return $a
}


Zur Info:
Das Zeilen zählen geht schneller:

function getZeile(){
  return (Get-content "C:\Program Files\Service1\service.log").count-1
}


#10 BNils

BNils

    Newbie

  • 15 Beiträge

 

Geschrieben 13. Januar 2010 - 13:39

if ((Get-Content file.log | Select-Object -Last 1) -match "quit"){
#Your Code here
}


Das ist super, dann habe ich eine Pipe weniger :)

Danke @Dukel

EDIT: Kann es sein, das er mit -last trotzdem vorne anfängt und jede Zeile durchläft bis er bei der letzten ist? Kann man das anders machen, weil es dauert bei meiner log (80.000 Zeilen) lange bis er bei der letzten Zeile ist!

Bearbeitet von BNils, 13. Januar 2010 - 14:02.


#11 P.Foeckeler

P.Foeckeler

    Junior Member

  • 117 Beiträge

 

Geschrieben 16. Januar 2010 - 17:32

Hallo Nils,

mit Get-Content wird leider ebenfalls die gesamte Datei ausgelesen, deswegen dauert es so lange (Get-Content bringt immerhin als Ausgabe ein Array mit allen Zeilen der Datei....).

Du mußt das schon direkt mit einem .NET FileStream oder was ähnlichem anpacken. Da kannst Du den Lese-Zeiger direkt aufs Ende setzen und gehst dann zurück, bis du zum erstem Ml auf Character 10 (Line Feed) triffst, das wäre dann der letzte Zeilenumbruch, von da ab liest Du dann die Zeile. So wird von der Datei wirklich nur die letzte Zeile gelesen. Allerdings ist der Powershell-Code sehr häßlich, weil wie gesagt ein .NET-Objekt benutzt werden muß.

Hier ein möglicher Code-Entwurf (es gibt wahrscheinlich noch Probleme, wenn die Datei von einem anderen Programm gerade exklusiv geöffnet ist...):

$path = "C:\test.txt"
$reader = New-Object System.IO.StreamReader($path, $true)
[long]$pos = $reader.BaseStream.Length - 1
while($pos -gt 0)
{
     $reader.BaseStream.Position = $pos
     if ($reader.BaseStream.ReadByte() -eq 10)  {break}
     $pos--
}
$line = $reader.ReadLine()
$reader.Close()
$line

Das gibt die letzte Zeile aus. Auch wenn diese eine Leerzeile ist. Um die letzte nicht-leere Zeile zu bekommen, müßte man ein bisschen was ändern...

Gruß,
Philipp

#12 BNils

BNils

    Newbie

  • 15 Beiträge

 

Geschrieben 03. Februar 2010 - 16:07

Hier ein möglicher Code-Entwurf (es gibt wahrscheinlich noch Probleme, wenn die Datei von einem anderen Programm gerade exklusiv geöffnet ist...)


Genau das ist nun das Problem :(

Aber vielen dank, für die Idee!

Gruß Nils

#13 P.Foeckeler

P.Foeckeler

    Junior Member

  • 117 Beiträge

 

Geschrieben 03. Februar 2010 - 22:30

OK, für einen kompletten Parallel-Zugriff mußt du erst einen System.IO.FileStream öffnen, da kann man entsprechende FileMode/FileAccess Parameter übergeben, den Streamreader erzeugst Du dann auf der Basis vom Filestream.....es müßte ungefähr so gehen:
$path = "C:\test.txt"

$open = [System.IO.FileMode]::Open
$read = [System.IO.FileAccess]::Read
$share =  [System.IO.FileShare]::Read

$stream = New-Object System.IO.FileStream(($path, $open, $read, $share)
$reader = New-Object System.IO.StreamReader($path, $true)

...der Rest dann wie gehabt. :cool:

Gruß,
Philipp

#14 BNils

BNils

    Newbie

  • 15 Beiträge

 

Geschrieben 04. Februar 2010 - 10:23

Das funktioniert nicht, er sagt immer noch das der Prozess von einem anderen Programm geöffnet ist...

Hast du noch eine idee :)

Gruß Nils

EDIT: Ich habe das ganze nun mi tail.exe aus dem Windows Resource Kit gelöst... das funktioniert super :)

Trotzdem danke

Bearbeitet von BNils, 04. Februar 2010 - 12:15.


#15 blub

blub

    Moderator

  • 7.605 Beiträge

 

Geschrieben 10. Februar 2010 - 17:15

ich habe mir eine LogDatei mit 140.000 Zeilen erstellt (3-mal das Windowsupdatelog in eine Textdatei kopiert)

mit diesem Code bekomme ich auf einem virtuellen Win7-Rechner die letzte Zeile in weniger als 5 Sekunden zurück

$inhalt=get-content c:\temp\windowsupdate.log 
$letzteZeile=$($inhalt.length)
$inhalt[$letzteZeile-1]

Welche Zeit strebst du denn an?

cu
blub

Ein Kluger bemerkt alles, Ein Dummer macht über alles eine Bemerkung. (Heinrich Heine)