Quiero convertir mi archivo txt a xls/csv.
La primera fila debe imprimir la fecha y hora y la segunda fila debe imprimir todos los datos restantes (desde tid hasta la tabla en el siguiente ejemplo)
Cuando estoy usando el siguiente comando
awk 'BEGIN{ OFS="\t"; print "DateTime,Error"}; NR > 1{print $1,$2;}' TMP.txt > Output.xls
Se imprime la fecha y hora en la primera fila, pero solo se imprime el tid en la siguiente columna.
¿Alguien puede ayudarme a imprimir todo el texto restante en la segunda columna?
Grabar en archivo de texto:
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
También se deben considerar los siguientes tipos de entradas de registro:
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
Respuesta1
El motivo del comportamiento que ve es que, de forma predeterminada, awk
trata WHITESPACE
(es decir, espacio, tabulación) como separador de campo de entrada. De este modo,cadaEl elemento en su archivo de entrada que está rodeado por un espacio se trata como un "campo" único y se le asigna su propia $<number>
variable interna. Su awk
comando, sin embargo, indica awk
imprimir solo los dos primeros campos ( $1
y $2
), que en su caso son la cadena de fecha/hora y el literal tid:
.
En su caso particular, la forma más sencilla podría ser utilizar sed
para reemplazar elprimeroespacios en blanco mediante un tabulador, que debería dar el resultado deseado.
Como también desea incluir una línea de encabezado, lo siguiente debería funcionar (suponiendo que sed
se esté utilizando GNU):
sed -e '1 i\DateTime\tError' -e 's/ /\t/' TMP.txt > Output.txt
La primera expresión inserta una línea de texto al principio de la línea, la segunda realiza el "formato real" previsto.
Actualizar
Para el formato de cadena adicional que proporcionó, recurriría a awk
en lugar de sed
(tenga en cuenta que uso GNU awk):
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
Esta expresión regular coincide con un formato de hora especificado por usted, seguido de uno o más espacios, seguido de caracteres imprimibles arbitrarios hasta el final de la línea, e imprime el primer (...)
subgrupo, la marca de tiempo, luego a \t
y luego el segundo. (...)
subgrupo, que es "el resto de la línea". Además, el BEGIN
ancla se utiliza para insertar la línea del encabezado en la parte superior.
Como ambos casos pueden darse en un mismo archivo, tenemos que combinarlos en un solo awk
programa:
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]);
}
Puede llamar al script anterior xlsconvert.awk
y luego llamarlo como
user@host$ awk -f xlsconvert.awk TMP.txt > Output.txt
Tenga en cuenta que esto, por supuesto, mantendrá los diferentes formatos de marca de tiempo en la salida. Si desea convertirlo a un formato unificado, es posible que deba recurrir a un script de shell.