Ich möchte meine TXT-Datei in XLS/CSV konvertieren.
Die erste Zeile sollte Datum und Uhrzeit drucken und die zweite Zeile alle restlichen Daten (von TID bis Tabelle im folgenden Beispiel).
Wenn ich den folgenden Befehl verwende
awk 'BEGIN{ OFS="\t"; print "DateTime,Error"}; NR > 1{print $1,$2;}' TMP.txt > Output.xls
In der ersten Zeile wird das Datum und die Uhrzeit gedruckt, in der nächsten Spalte jedoch nur die Zeitangabe.
Kann mir bitte jemand helfen, den gesamten verbleibenden Text in der zweiten Spalte auszudrucken
Eintrag in Textdatei:
2019-11-26T11:51:32.087-08:00 tid: JCA-work-instance:AQ Adapter-8 userId: <anonymous> 0 , APP: Service Bus Logging FlowId: 0000MtDbHiu8pmk5Szd9ic1TlVox0015xl RouteNode2, null, null, REQUEST Queried data from header table
Die folgenden Arten von Protokolleinträgen sollten ebenfalls berücksichtigt werden:
Nov 28, 2019 8:19:03 AM PST HTTP BEA-101019 [ServletContext[text] Servlet failed with an IOException.
Nov 28, 2019 8:22:40 AM PST [null, null, null, ERROR] error in service-callouterror service to get information
Antwort1
Der Grund für das Verhalten, das Sie sehen, ist, dass standardmäßig (also Leerzeichen, Tabulator) als Eingabefeldtrennzeichen awk
behandelt wird . DaherWHITESPACE
jedenEin Element in Ihrer Eingabedatei, das von Leerzeichen umgeben ist, wird als einzelnes „Feld“ behandelt und erhält eine eigene $<number>
interne Variable. Ihr awk
Befehl weist jedoch an, nur die ersten beiden dieser Felder ( und ) awk
auszudrucken , was in Ihrem Fall die Datums-/Uhrzeitzeichenfolge und das Literal sind .$1
$2
tid:
In Ihrem speziellen Fall könnte der einfachste Weg sein, zu verwenden, sed
um dieErsteLeerzeichen durch einen Tabulator, was zum gewünschten Ergebnis führen sollte.
Da Sie auch eine Kopfzeile einfügen möchten, sollte Folgendes funktionieren (vorausgesetzt, sed
es wird GNU verwendet):
sed -e '1 i\DateTime\tError' -e 's/ /\t/' TMP.txt > Output.txt
Der erste Ausdruck fügt den Text am Zeilenanfang ein, der zweite führt die „eigentliche Formatierung“ durch.
Aktualisieren
Für das zusätzliche Zeichenfolgenformat, das Sie bereitgestellt haben, würde ich awk
stattdessen auf Folgendes zurückgreifen sed
(beachten Sie, dass ich GNU awk verwende):
awk 'BEGIN{printf("DateTime\tError\n")} {match($0,"^([[:alpha:]]{3}[[:space:]]+[0123]?[[:digit:]],[[:space:]]+20[[:digit:]]{2}[[:space:]]+[01]?[[:digit:]]:[012345][[:digit:]]:[012345][[:digit:]][[:space:]]+[AP]M[[:space:]]+[[:alpha:]]+)[[:space:]]+([[:print:]]*)$", fields); printf("%s\t%s\n", fields[1], fields[2])}' TMP.txt > Output.txt
Dieser reguläre Ausdruck sucht nach einem von Ihnen angegebenen Zeitformat, gefolgt von einem oder mehreren Leerzeichen, gefolgt von beliebigen druckbaren Zeichen bis zum Ende der Zeile, und druckt die erste (...)
Untergruppe, den Zeitstempel, dann ein \t
und dann die zweite (...)
Untergruppe, die „der Rest der Zeile“ ist. Zusätzlich BEGIN
wird der Anker verwendet, um die Kopfzeile oben einzufügen.
Da beide Fälle in derselben Datei auftreten können, müssen wir sie in einem einzigen awk
Programm kombinieren:
BEGIN {
printf("DateTime\tError\n");
}
{
if (match($0,"^([[:alpha:]]{3}[[:space:]]+[0123]?[[:digit:]],[[:space:]]+20[[:digit:]]{2}[[:space:]]+[012]?[[:digit:]](:[012345][[:digit:]]){2}[[:space:]]+[AP]M[[:space:]]+[[:upper:]]+)[[:space:]]+([[:print:]]*)$", fields) == 0)
match($0,"^(20[[:digit:]]{2}-[01][[:digit:]]-[0123][[:digit:]][[:alpha:]][012][[:digit:]](:[012345][[:digit:]]){2}.[[:digit:]]{3}[+-][012][[:digit:]]:[012345][[:digit:]])[[:space:]]+([[:print:]]*)$", fields);
printf("%s\t%s\n", fields[1], fields[3]);
}
Sie können das obige Skript aufrufen xlsconvert.awk
und es dann als
user@host$ awk -f xlsconvert.awk TMP.txt > Output.txt
Beachten Sie, dass dadurch natürlich die unterschiedlichen Zeitstempelformate in der Ausgabe erhalten bleiben. Wenn Sie diese in ein einheitliches Format konvertieren möchten, müssen Sie möglicherweise auf ein Shell-Skript zurückgreifen.