2016-07-29 5 views
0

Ich möchte einige Daten in mehreren Zeilen in eine Zeile mit einem regulären Ausdruck umwandeln.Wie pivotieren Sie Daten in Perl nur mit Regex?

Die Daten bestehen aus Start- und Endbenachrichtigungen für HTTP-Austauschvorgänge gefolgt von Details, die in einer oder mehreren Zeilen geschrieben wurden. Hier ist die regex für das Erledigen der Arbeit:

(\d+-\d+-\d+) (\d+:\d+:\d+,\d+) INFO (\[com\.LoggingFilter\]) \(([^)]+)\) (\d+) \* Server in-bound request 
(?=\5 > (.+) 
[\s\S]* 
\5 > user-agent:\s*(.+) 
[\s\S]* 
(\d+-\d+-\d+) (\d+:\d+:\d+,\d+) INFO \3 \(\4\) \5 \* Server out-bound response 
\5 < (\d+) 
[\s\S]*) 

It (fast) funktioniert: VIEW regex in action. Einige Details (erhalten durch die positive Vorschau) werden nach dem Regex-Austausch beibehalten. Wie das folgende Ergebnis

"88598";"2016-07-29";"00:00:08,262";"2016-07-29";"00:00:08,262";"http-10.2.3.4-8080-14";"Java/1.7.0_79";"303";"GET http://1.2.3.4:8080/service/api/ 
"88599";"2016-07-29";"00:00:08,382";"2016-07-29";"00:00:08,382";"http-10.2.3.4-8080-8";"Java/1.7.0_79";"303";"GET http://1.2.3.4:8080/service/api/" 
(...) 

statt

"88598";"2016-07-29";"00:00:08,262";"2016-07-29";"00:00:08,262";"http-10.2.3.4-8080-14";"Java/1.7.0_79";"303";"GET http://1.2.3.4:8080/service/api/"88598 > GET http://1.2.3.4:8080/service/api/ 
<garbage data here> 
"88599";"2016-07-29";"00:00:08,382";"2016-07-29";"00:00:08,382";"http-10.2.3.4-8080-8";"Java/1.7.0_79";"303";"GET http://1.2.3.4:8080/service/api/"88599 > GET http://1.2.3.4:8080/service/api/ 
(...) 
+0

Sie haben uns Ihre Regex, die Ausgabe, die Sie erhalten, und die Ausgabe, die Sie erhalten möchten, gegeben. Das ist alles großartig. Was uns fehlt, ist ein Beispiel für die Eingabedaten. –

+2

@DaveCross Es ist in der Regex-Demo. – horcrux

+2

"Nur mit Regex" ist ein schlechter Ansatz (ineffizient), sollten Sie eine Zeile für Zeile oder einen Block Ansatz betrachten. –

Antwort

0

bekommen Dies scheint zu funktionieren:

(\d+-\d+-\d+) (\d+:\d+:\d+,\d+) INFO (\[com\.LoggingFilter\]) \(([^)]+)\) (\d+) \* Server in-bound request 
(?=\5 > (.+) 
[\s\S]* 
\5 > user-agent:\s*(.+) 
[\s\S]* 
(\d+-\d+-\d+) (\d+:\d+:\d+,\d+) INFO \3 \(\4\) \5 \* Server out-bound response 
\5 < (\d+) 
[\s\S]*)[\s\S]*?((?=\n.*Server in-bound request)|(?![\s\S])) 

Here die Demo.

+0

Wenn "Inbound-Serveranforderung" im Papierkorb angezeigt wird, wird sie im Endergebnis gespeichert. Siehe: https://regex101.com/r/tS9aD7/2 – Stephan

+0

In gewisser Weise sollten Sie ein Kriterium haben, um Müll von Nicht-Müll Zeug zu unterscheiden. Wenn "\ n. * Inbound-Serveranforderung" im Papierkorb angezeigt werden kann, ersetzen Sie sie durch etwas, das unwahrscheinlicher erscheint. Zum Beispiel das gesamte \ n \ d + - \ d + - \ d + \ d +: \ d +: \ d +, \ d + INFO + \ [com \ .LoggingFilter \] \ ([^)] + \) \ d + \ * Server eingehende Anfrage? Siehe [hier] (https://regex101.com/r/tS9aD7/3). – horcrux

+0

Ihr Muster benötigt viele Schritte, um die Übereinstimmung zu finden, und ich vermute, dass die tatsächliche Datei größer als das Muster ist. Aufgrund dieser Muster können Sie schnell die Backtracking-Grenze erreichen. Selbst wenn ich denke, dass der Ansatz * only regex * nicht geeignet ist, habe ich versucht, das Muster zu verbessern, um die Anzahl der Schritte zu reduzieren. Das Ergebnis finden Sie hier: https://regex101.com/r/lT4vV4/1 –