Helmer 1 Geschrieben 10. September Melden Teilen Geschrieben 10. September Hallo zusammen, ich bin auf der Suche nach einer Möglichkeit innerhalb einer Textdatei nach einem Text zu suchen und den Textblock / Datensatz, welcher diesen enthält auszugeben. Der Anfang des Bereichs ist immer eine Zeile mit MSH am Anfang, beim nächsten MSH beginnt ein neuer Bereich (Logfiles einer medizinischen HL7-Schnittstelle < Beispiel unten stark gekürzt). Wenn innerhalb dieses Blocks der String "7909264350" gefunden wird, den entsprechenden gesamten Block ausgeben (im Beispiel fett markiert). MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|ST|BI-032^Erreg OBR|2|WKC097U|WKC097U OBX|1|ST|BI-685^Staph OBR|3|WKC097U|WKC097U OBX|1|ST|BI-PROT1^Bef NTE|1|L|Kulturelles W MSH|^~\&|ME PID|1||7902183713| PV1|1||^^^^^^^^2938||||||||||||||||7909264350| ORC|OK|WKC058S|WKC OBR|1|WKC058S|WKC0 OBX|1|ST|BI-032^Er OBR|2|WKC058S|WKC0 OBX|1|ST|BI-603^Prot OBR|3|WKC058S|WKC058S OBX|1|ST|BI-PROT1^Bef NTE|1|L|Kulturelles Wach OBR|4|WKC058S|WKC058S-1| OBX|1|ST|BI-PROT2^Befund NTE|1|L|Antibiogramm sie OBR|5|WKC058S|WKC058S-1| OBX|1|ST|BI-ICD109^ICD10 NTE|1|L|A40-A41 Bakterie NTE|2|L|T82.7 Sepsis bei MSH|^~\&|ME PID|1||7903126877| PV1|1||^^^^^^^^2825||||||||||||||||7909265076| ORC|OK|WKC118D|WKC OBR|1|WKC118D|WKC1 OBX|1|ST|BI-032^Er OBR|2|WKC118D|WKC1 OBX|1|ST|BI-673^St OBR|3|WKC118D|WKC1 OBX|1|ST|BI-PROT1^ NTE|1|L|Zusätzlich OBR|4|WKC118D|WKC1 OBX|1|NM|BI-ATB^An OBR|5|WKC118D|WKC1 OBX|1|ST|BI-RES^Me NTE|1|L|Antibiogra NTE|2|L|Wirkstoff NTE|3|L|Penicillin NTE|4|L|Oxacillin NTE|5|L|Ampicillin Ideen? - Danke fürs Lesen Grüße Helmut Zitieren Link zu diesem Kommentar
BOfH_666 577 Geschrieben 10. September Melden Teilen Geschrieben 10. September Helmut, Willkommen im MCSEboard. vor 48 Minuten schrieb Helmer: Ideen? Ne Menge. Gegenfrage: Wie weit bist Du denn schon mit Deinem Script/Code? Wo genau bleibst Du stecken? Magst Du den Code zeigen? Ganz allgemein: Nur in ganz seltenen Fällen, ist man mit einer gegeben Aufgabe, der erste. Meistens gibt es bereits Code-Beispiele, die man an seine eigenen Anforderungen anpassen kann. Hast Du denn schon mal gesucht? StackOverflow ist das ein guter Startpunkt. Mit einer schnellen Suche, hab ich schon mal das hier gefunden: https://stackoverflow.com/a/75656236 Damit könntest Du ja schon mal anfangen. Und da gibt's bestimmt auch noch mehr. Zitieren Link zu diesem Kommentar
testperson 1.707 Geschrieben 10. September Melden Teilen Geschrieben 10. September (bearbeitet) Hi, ein "Anfang" wäre: $LogFile = "C:\Install\Test\Log.txt" $LogContent = Get-Content -Path $LogFile ` -Raw $Content = $LogContent -split "(?=MSH\|)" | Where-Object { -not [string]::IsNullOrEmpty($_) } Was du jetzt mit $Content anstellst, bleibt dir überlassen. Das ist zwar grob auch im Stackoverflow Artikel zu lesen, aber nunja.. HTH Jan BTW: Das "Where-Object" lässt sich bestimmt auch noch umschiffen oder man lebt einfach mit einem leeren ersten Objekt, wenn es stört. bearbeitet 10. September von testperson Zitieren Link zu diesem Kommentar
daabm 1.366 Geschrieben 10. September Melden Teilen Geschrieben 10. September Queue fällt mir spontan ein... https://powershell.works/2021/09/29/lifo-fifo-with-powershell/ Sobald ich den Marker finde, schiebe ich in die Queue. Wenn ich den nächsten finde und in der Zwischenzeit das Tag vorbeikam, hole ich erst alles wieder raus und "mach irgendwas damit". Kam kein Tag vorbei, schmeiße ich die Queue weg. Dann schiebe ich den aktuellen Marker rein und loope mich so durch. Und wenn die Logs groß sind, noch ein StreamReader dazu. Aber mal sehen wie es weitergeht Zitieren Link zu diesem Kommentar
Helmer 1 Geschrieben 11. September Autor Melden Teilen Geschrieben 11. September Sehr interessante Ideen, danke euch dafür. Ich hatte bisher die Geschichte so weit getrieben, dass er mir die MSH Abschnitte aus dem Logfile holt und auf dem Schirm ausgibt. Misslungen ist mir bisher das Testen der einzelnen Blöcke auf das Vorhandensein des Suchstrings und deren Ausgabe (Blöcke mit vorhandenem Suchstring) in eine Datei. Es ist halt auch nicht wirklich einfach, hinter die Regex Syntax zu steigen.... Get-Content .\oru.log | Out-String | % {[Regex]::Matches($_, "(?<=MSH(.*))((.|\n)*?)(?=MSH(.*))")} | % {$_.Value} Zitieren Link zu diesem Kommentar
daabm 1.366 Geschrieben 11. September Melden Teilen Geschrieben 11. September Ja ok, wenn man das in einen Einzeiler quetscht, wird's unübersichtlich Warum man wohl nach Get-Content noch Out-String braucht? Struktrurierte Programme/Skrips sind natürlich länger und manchmal laufen sie auch langsamer. Aber sie sind besser zu warten. Mit Lazy/Greedy Regex machst Dir da keine Freunde, wenn das länger im Einsatz sein soll. 1 Zitieren Link zu diesem Kommentar
Helmer 1 Geschrieben 12. September Autor Melden Teilen Geschrieben 12. September Am 10.9.2024 um 10:53 schrieb testperson: $LogFile = "C:\Install\Test\Log.txt" $LogContent = Get-Content -Path $LogFile ` -Raw $Content = $LogContent -split "(?=MSH\|)" | Where-Object { -not [string]::IsNullOrEmpty($_) } Die Ausgabe erzeugt eine schön in "Blöcke" formatierte Datei.... Lässt sich eine Überprüfung der einzelnen Blöcke einbauen, welche nur diese ausgibt, welche auch den Suchstring enthalten? Zitat Wenn innerhalb dieses Blocks der String "7909264350" gefunden wird, den entsprechenden gesamten Block ausgeben (im Beispiel fett markiert). Am 10.9.2024 um 18:41 schrieb daabm: Queue fällt mir spontan ein... https://powershell.works/2021/09/29/lifo-fifo-with-powershell/ Sobald ich den Marker finde, schiebe ich in die Queue. Wenn ich den nächsten finde und in der Zwischenzeit das Tag vorbeikam, hole ich erst alles wieder raus und "mach irgendwas damit". Kam kein Tag vorbei, schmeiße ich die Queue weg. Dann schiebe ich den aktuellen Marker rein und loope mich so durch. Und wenn die Logs groß sind, noch ein StreamReader dazu. Aber mal sehen wie es weitergeht ... ich gebe zu, dass ich sehr grün hinter den Ohren bin, was PS-Scripts angeht. Hier sehe ich nicht wirklich eine Umsetzungsmöglichkeit von deiner durchaus Sinnigen Beschreibung in Bezug auf das, was ich über lifo/fifo gefunden habe. Sorry da klickt es nicht bei mir.... Zitieren Link zu diesem Kommentar
testperson 1.707 Geschrieben 12. September Melden Teilen Geschrieben 12. September vor 11 Minuten schrieb Helmer: Lässt sich eine Überprüfung der einzelnen Blöcke einbauen, welche nur diese ausgibt, welche auch den Suchstring enthalten? Ja, lässt sich einbauen. Da du das vor 12 Minuten schrieb Helmer: ... ich gebe zu, dass ich sehr grün hinter den Ohren bin, was PS-Scripts angeht. ja ändern möchtest, was hast du denn bereits unternommen, um die passenden Arrays auszugeben? 1 Zitieren Link zu diesem Kommentar
daabm 1.366 Geschrieben 12. September Melden Teilen Geschrieben 12. September (bearbeitet) vor 10 Stunden schrieb Helmer: ... ich gebe zu, dass ich sehr grün hinter den Ohren bin, was PS-Scripts angeht. Das hat noch gar nicht mit Powershell zu tun, sondern mit PAP - Programm Ablauf Plan Bevor ich anfange, etwas umzusetzen, muss ich mir ja die Logik dahinter überlegen, die am besten zum Problem - nein, zur Herausforderung 😂 - passt. Und das führt ganz oft zu völlig unterschiedlichen Ergebnissen. So als Pseudo-Code: InterestingBlocks = [Array] Foreach Line Add Line to Queue If Line Contains InterestingString InterestingStringFound = true End If If Line Contains Marker # jetzt sind wir beim nächsten Marker "MSH" - haben wir den gesuchten String im letzten Block gefunden? If InterestingStringFound Add Queue to InterestingBlocks End If # Danach Queue wegwerfen und von neuem füllen bis zum nächsten "MSH" Empty Queue End If Next Statt der Queue kann man natürlich auch ein Hilfsarray verwenden, das alle in der Zwischenzeit gelesenen Zeilen aufnimmt. Queue ist halt deutlich schneller. bearbeitet 12. September von daabm Zitieren Link zu diesem Kommentar
Helmer 1 Geschrieben 15. September Autor Melden Teilen Geschrieben 15. September Hallo in die Runde, ich habe mich noch ein paar Stunden mit dem „Problem“ beschäftigt und wollte es „einfach“ machen. Die Beispieldatei von oben wird eingelesen und Zeilenweise in eine Queue geschrieben. Diese wird als erstes auf das Blockende hin untersucht, wenn dies gefunden, in einer zweiten if Schleife hin auf den Inhalt des Suchbegriffs. Wenn dieser gefunden, wird der Inhalt der Queue auf den Schirm ausgegeben. Da die Zeile nach dem Blockende immer der Start eines neuen Blocks ist, sollte auch immer nach dem „Blockende gefunden > Queue gelöscht“ ein neuer Block in der Queue angelegt werden. Ich mache es kurz, es geht nicht (siehe Ausgabe am Ende). Die Queue wird nicht nach den beiden Suchbegriffen durchsucht. Zudem wird die Queue nicht Zeilenweise um Einträge ergänzt. Es wird in der Queue dem ersten Eintrag direkt die nächste Zeile aus der Quelldatei angehängt und keine neue „Zeilen / Einträge“ in der Queue erzeugt. Beim zweiten "write-host $Queue;" findet keine Ausgabe eines kompletten Blocks statt. $Queue.Contains($SuchString) sucht nicht nach dem $SuchString irgendwo innerhalb der Queue? Die beiden Suchstrings „ORC“ und „PID“ sind nur beispielhaft ausgewählt < machen später keinen Sinn. $Queue = New-Object System.Collections.Queue $LogFile = "d:\powershell\hl7.log" $BlockEnde = "ORC" $SuchString = "PID" foreach ($i in Get-Content -Path $LogFile){ $Queue.Enqueue($i) write-host $Queue #Nur Kontrolle ob Queue sich füllt - Ausgabe siehe unten if ($Queue.Contains($BlockEnde)) { if ($Queue.Contains($SuchString)) { write-host $Queue #leider keine Ausgabe $Queue.Clear()} } pause #wieder eine Kontrolle wird Zeilenweise ausgeführt } kommt zu der Ausgabe: PS PS D:\Powershell> .\sort6.ps1 MSH|^~\&|MEL Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|S T|BI-032^Erreg Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|S T|BI-032^Erreg OBR|2|WKC097U|WKC097U Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|S T|BI-032^Erreg OBR|2|WKC097U|WKC097U OBX|1|ST|BI-685^Staph Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|S T|BI-032^Erreg OBR|2|WKC097U|WKC097U OBX|1|ST|BI-685^Staph OBR|3|WKC097U|WKC097U Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|S T|BI-032^Erreg OBR|2|WKC097U|WKC097U OBX|1|ST|BI-685^Staph OBR|3|WKC097U|WKC097U OBX|1|ST|BI-PROT1^Bef Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|S T|BI-032^Erreg OBR|2|WKC097U|WKC097U OBX|1|ST|BI-685^Staph OBR|3|WKC097U|WKC097U OBX|1|ST|BI-PROT1^Bef NTE|1|L|Kulturelles W Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...: MSH|^~\&|MEL PID|1||7903313686| PV1|1||^^^^^^^^2825||||||||||||||||7909260637| ORC|OK|WKC097U|WKC097U- OBR|1|WKC097U|WKC097U-1 OBX|1|S T|BI-032^Erreg OBR|2|WKC097U|WKC097U OBX|1|ST|BI-685^Staph OBR|3|WKC097U|WKC097U OBX|1|ST|BI-PROT1^Bef NTE|1|L|Kulturelles W MSH|^~\&| ME Zitieren Link zu diesem Kommentar
Dukel 455 Geschrieben 15. September Melden Teilen Geschrieben 15. September Wenn du es einfach haben willst, lass die Queue weg. $LogFile = "d:\powershell\hl7.log" $BlockEnde = "ORC" $SuchString = "PID" $found = $false foreach ($i in Get-Content -Path $LogFile){ if($i -contains $SuchString){ $found = $true } if($i -contains $BlockEnde){ $found = $false } if($found){ $i } } Zitieren Link zu diesem Kommentar
Lian 2.436 Geschrieben 16. September Melden Teilen Geschrieben 16. September @Helmer: Füge bitte Script-Code oder Ausgaben in den passenden Block hier in das Forum ein. Dazu die Schaltfläche im Editor </> nutzen. Zitieren Link zu diesem Kommentar
testperson 1.707 Geschrieben 16. September Melden Teilen Geschrieben 16. September Am 12.9.2024 um 08:22 schrieb Helmer: Am 10.9.2024 um 10:53 schrieb testperson: $LogFile = "C:\Install\Test\Log.txt" $LogContent = Get-Content -Path $LogFile ` -Raw $Content = $LogContent -split "(?=MSH\|)" | Where-Object { -not [string]::IsNullOrEmpty($_) } Die Ausgabe erzeugt eine schön in "Blöcke" formatierte Datei.... Lässt sich eine Überprüfung der einzelnen Blöcke einbauen, welche nur diese ausgibt, welche auch den Suchstring enthalten? Ich ergänze mal um ein $Content -match "7909264350" Sollte der Suchstring noch an anderen Stellen vorkommen können, muss halt noch ein bisschen RegEx drumrum. Zitieren Link zu diesem Kommentar
Sunny61 807 Geschrieben 16. September Melden Teilen Geschrieben 16. September vor 10 Stunden schrieb Helmer: zweiten if Schleife Klugsc***modus an: If ist keine Schleife, sondern eine Bedingung. Zitieren Link zu diesem Kommentar
cj_berlin 1.329 Geschrieben 16. September Melden Teilen Geschrieben 16. September vor 9 Stunden schrieb Dukel: Wenn du es einfach haben willst, lass die Queue weg. $LogFile = "d:\powershell\hl7.log" $BlockEnde = "ORC" $SuchString = "PID" $found = $false foreach ($i in Get-Content -Path $LogFile){ if($i -contains $SuchString){ $found = $true } if($i -contains $BlockEnde){ $found = $false } if($found){ $i } } Moin, -contains funktioniert nicht bei Strings, aber von der Logik her kann das so gehen, mit -like, -match oder .StartsWith(). Wenn man die letzte Zeile (mit "ORC") mit ausgegeben haben möchte, müssen die zweite und die dritte Bedingung vertauscht werden. 1 Zitieren Link zu diesem Kommentar
Empfohlene Beiträge
Schreibe einen Kommentar
Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.