Я хочу преобразовать свой txt-файл в xls/csv.
Первая строка должна вывести дату и время, а вторая строка должна вывести все оставшиеся данные (от tid до таблицы в примере ниже)
При использовании следующей команды
awk 'BEGIN{ OFS="\t"; print "DateTime,Error"}; NR > 1{print $1,$2;}' TMP.txt > Output.xls
В первой строке печатается дата и время, а в следующем столбце — только время.
Может ли кто-нибудь помочь мне напечатать весь оставшийся текст во втором столбце?
Запись в текстовом файле:
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
Также следует учитывать следующие типы записей в журнале:
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
решение1
Причина поведения, которое вы видите, заключается в том, что по умолчанию (т.е. пробел, табуляция) awk
рассматривается как разделитель поля ввода. Таким образом,WHITESPACE
каждыйэлемент в вашем входном файле, окруженный пробелом, рассматривается как одно "поле" и ему назначается собственная $<number>
внутренняя переменная. awk
Однако ваша команда предписывает awk
печатать только первые два таких поля ( $1
и $2
), которые в вашем случае являются строкой даты/времени и литералом tid:
.
В вашем конкретном случае самым простым способом может быть использование sed
для заменыпервыйпробелы табулятором, что должно дать желаемый результат.
Поскольку вы также хотите включить строку заголовка, следующее должно сработать (при условии, что sed
используется GNU):
sed -e '1 i\DateTime\tError' -e 's/ /\t/' TMP.txt > Output.txt
Первое выражение вставляет одну строку текста в начало строки, второе выполняет предполагаемое «фактическое форматирование».
Обновлять
Для дополнительного формата строки, который вы предоставили, я бы прибегнул к следующему awk
вместо sed
(обратите внимание, что я использую 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
Это регулярное выражение сопоставляет указанный вами формат времени, за которым следует один или несколько пробелов, за которыми следуют произвольные печатные символы до конца строки, и печатает первую (...)
подгруппу, временную метку, затем \t
, а затем вторую (...)
подгруппу, которая является «остальной частью строки». Кроме того, якорь BEGIN
используется для вставки строки заголовка сверху.
Поскольку оба случая могут встречаться в одном и том же файле, нам придется объединить их в одну awk
программу:
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]);
}
Вы можете вызвать приведенный выше скрипт xlsconvert.awk
, а затем вызвать его как
user@host$ awk -f xlsconvert.awk TMP.txt > Output.txt
Обратите внимание, что это, конечно, сохранит различные форматы временных меток в выводе. Если вы хотите преобразовать это в унифицированный формат, вам, возможно, придется прибегнуть к скрипту оболочки.