2016-08-19 6 views
0

Arbeiten an einem Skript zum Extrahieren von Daten aus der Protokolldatei; Begriffe in einer Suchanfrage und Ausführungszeit.Powershell-Regex zum Extrahieren von Daten aus der Protokolldatei

Probe aus der Protokolldatei

19/08/2016 09:08:00 [100] ACTION%3DQuery%26MaxResults%3D9999%26abridged%3Dtrue%26abridgedmeta%3Ddatabase%26printfields%3DIM_DOCNUM,IM_VERSION%26combine%3Dfieldcheck%26databasematch%3DDATABASE_1,DATABASE-2%26Text%3D((pep21556)%3AIM_DOCNAME)%26fieldtext%3D(WILD%7BWORK%7D%3AIM_PRJ_SUBTYPE+AND+WILD%7BWEBDOC%7D%3AIM_CLASS)+AND+BIASDATE%7B1471612079e,2592000,20%7D%3Aautn_date+AND+BIASDATE%7B1471612079e,63072000,20%7D%3Aautn_date%26anyLanguage%3Dtrue%26TimeoutMS%3D60000 
19/08/2016 09:08:00 [100] Request completed in 12 ms. 
19/08/2016 09:08:28 [103] Request from 10.1.1.131 

die Protokolldatei URL codiert.

Mein unfertiger Skript lädt die Protokolldatei

foreach ($line in [System.IO.File]::ReadLines($filename)) 

dann URLdecods jede Zeile und entfernt eine lange Sicherheitsinfo String

$VarURLDecoded = [System.Web.HttpUtility]::UrlDecode($line) -replace "SecurityInfo=.*" 

Jetzt mit der RegEx habe Schwierigkeiten ich folgendes zu extrahieren: Datum + Zeit, MaxResault = xxxxxxx, Text = ((??????????): ???????) und die Zeit in ms für die Anforderung in der folgenden Zeile.

$findText = $VarURLDecoded | select-string -Inputobject {$_} -pattern 

Ich habe einige Teile Regex Teile.

Aber kann nicht herausfinden, die AND-Syntax zu ihnen alle einschließlich der Dauer Datensatz, der in der zweiten Zeile ist. Verwenden Sie entweder die Tatsache, dass sie der darunter liegenden Zeile folgt oder dass sie einen korrekten Zeitstempel hat.

Sobald ich die grundlegende Regex funktioniert habe, kann ich Komplexität hinzufügen, indem ich benannte Gruppen hinzufüge und die Ergebnisse in eine Hash-Tabelle exportiere.

Antwort

2

Nach dem veröffentlichten Protokoll zu urteilen, gibt es keine Notwendigkeit, es zu dekodieren, da es keine %xx-codierten Zeichen gibt.
Für die Textverarbeitung gibt es keine Notwendigkeit für ein Low-Level-Zeug wie [System.IO.File].
Eine zusätzliche Zeile wird benötigt, also verwenden wir -context before, after Parameter.

$report = select-string -path $filename -context 0,1 -pattern (
    '^(?<date>.+?) ' + 
    '(?<time>.+?) .+?' + 
    '&MaxResults=(?<results>\d+).+?' + 
    '&Text=(?<text>[^&]+)') | 
%{ 
    $nextLine = $_.Context.PostContext[0] 
    $g = $_.matches[0].groups 
    @{ 
     date = $g['date'].value 
     time = $g['time'].value 
     results = $g['results'].value 
     text = $g['text'].value 
     duration = if ($nextLine -match 'completed in (\d+) ms') { $matches[1] } 
    } 
} 

$report jetzt ist ein Array von Objekten jeweils wie folgt:

Name       Value 
----       ----- 
date       19/08/2016 
time       09:08:00 
duration      12 
results      9999 
text       ((pep21556):IM_DOCNAME) 

Alternativ kann bei Berücksichtigung select-string des Musterabgleich mit einem komplexen Muster langsam sein kann, lassen Sie uns übereinstimmen mit eine einfache Zeichenfolge, Filter mit ? (Alias ​​für Where-Object), dann bearbeiten Sie die Ergebnisse:

$report = select-string -path $filename -context 0,1 -pattern '&MaxResults=' -simpleMatch | 
?{ $_.Line -match (
    '^(?<date>.+?) ' + 
    '(?<time>.+?) .+?' + 
    '&MaxResults=(?<results>\d+).+?' + 
    '&Text=(?<text>[^&]+)') 
} | %{ 
    $nextLine = $_.Context.PostContext[0] 
    $m = $matches # $matches is set by the above -match 
    @{ 
     date = $m['date'] 
     time = $m['time'] 
     results = $m['results'] 
     text = $m['text'] 
     duration = if ($nextLine -match 'completed in (\d+) ms') { $matches[1] } 
    } 
} 
+0

Vielen Dank für Ihre Antwort auf meine zweite Frage. Ein paar Punkte, die Dateien, die ich suche, sind jeweils etwa 100 MB groß, also dachte ich, dass die Verwendung der [System.IO.File] bessere Leistung bringen würde. Und die Originaldaten sind URL-kodiert (ich habe das decodierte Sample eingefügt, um die Frage leichter zu erklären. Ich habe Ihren Code an mein ursprüngliches Skript angepasst, aber das Dauerfeld ist Bank. Ich frage mich, ob das daran liegt, dass es nicht funktioniert mit der system.IO.File – user3019228

+0

Tried :: readAllText anstelle von :: ReadLines und result war, dass das Skript nichts mehr findet, also welche Änderung wäre in Ihrem Lösungsskript erforderlich, um mit URLEncode-Zeilen zu arbeiten? (jede Datei ist wiederum etwa 100 MB groß) und hat fast 1 Million Zeilen) – user3019228

+1

Pipe die Zeilen: '[IO.File] :: ReadAllLines ($ filename) | select-string .....' – wOxxOm

Verwandte Themen