Извлечение даты из файла журнала и создание файла с уникальными датами

Я хотел бы извлечь из файла дату в формате DD.MM.YYYY , дата всегда в первой поместите здесь пример записей

15.04.2016 13:13:30,228 INFO    [wComService] [mukumukuko@system/3] Call created with id:VoiceConnector$mukumukuko@system$D1:1:0:CB:SESSION$D1:1:0:DB:mukumukuko@system$D1:1:0:HB:_TARGET^M
15.04.2016 13:14:10,886 INFO    [wComService] Call 5303 from device +41999999999^M
15.04.2016 13:14:20,967 INFO    [AddressTranslatorService][mukumukuko@system/3] </convertLocalToGNF>^M
15.04.2016 13:14:20,992 INFO    [wComService] [mukumukuko@system/3] Call created with id: VoiceConnector$mukumukuko@system$D1:1:0:MB:SESSION$D1:1:0:NB:mukumukuko@system$D1:1:0:RB:_TARGET^M
15.04.2016 13:15:18,760 INFO    [OSMCService] SessionManager Thread - Heartbeat (1clients connected)^M

этот файл содержит журнал активности за 1 неделю, поэтому в файле можно найти даты, например 16.04.2016 , 17.04.2016 , 18.04.2016 а также.

Файл может также иметь следующие выходные данные из исключения Java:

    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

Я пробовал следующее:

cat fac.log | sed 's/^.*\([0-9]\{2\}.[0-9]\{2\}.[0-9]\{4\}\).*$/\1/' > datesF1

но я получил желаемую дату в "dateF1", но с этими сообщениями об исключениях Java.

Я бы хотел чтобы сгенерировать файл, который отображает только уникальные даты без их повторения, например, «dateF1» должно быть:

15.04.2016
16.04.2016
17.04.2016
18.04.2016

Знаете ли вы, возможно ли это, или лучше использовать команду grep?

0
24.05.2016, 18:09
2 ответа

Причина, по которой ваша команда sed не работает, заключается в том, что она предполагает, что у вас есть дата в каждой строке, что не так, если некоторые строки поступают из многострочных сообщений об ошибках. Когда нет ничего, соответствующего шаблону замены, sed не выполняет замену, и списки стека вызовов, которые вы видели, остаются в выводе.

Чтобы получить даты только из строк, у которых они есть в начале, у вас есть несколько вариантов:

grep:

grep -Eo '^[0-9.]+' fac.log 

-o указывает grep печатать только соответствующую часть, а не всю строку, а -E включает "расширенные" регулярные выражения

awk:

awk '/^[0-9.]+/ {print $1}' fac.log

Первая часть команды awk - это совпадение регулярного выражения, остальное - что делать с совпадающей строкой, здесь мы печатаем первое слово в строке.

Perl:

perl -lne 'print $1 if /^([0-9]+)/' fac.log

-l: выводить новую строку на каждом print , -n: запускать команду для каждой строки ввода (например, awk), -e: просто сообщает, что программа дана на в командной строке, а не в файле.

Во всех случаях вы получаете одну строку вывода на соответствующую строку ввода, то есть повторяющиеся даты. Передача результата через | сортировать | uniq , вероятно, самая простая идиома для удаления дубликатов.

Обратите внимание, что я был ленив и использовал ^ [0-9.] + вместо более длинного и точного шаблона. Это связано с причиной, по которой мне нравится использовать perl вместо sed, awk и друзей: регулярные выражения Perl всегда одинаковы, независимо от того, что вы делаете.Также в Perl нет необходимости помнить, какие модификаторы поддерживаются по умолчанию, а какие требуют установки -E или чего-то еще. Кроме того, есть различия между версиями: по-видимому, в моих системах Debian по умолчанию используется mawk вместо GNU awk, и, похоже, он не поддерживает модификатор {N}, поэтому более точный шаблон не работал. Ой.

Руководство по GNU awk: «Интервальные выражения традиционно не были доступны в awk. Они были добавлены как часть стандарта POSIX, чтобы сделать awk и egrep согласованными друг с другом». (ref. https://www.gnu.org/software/gawk/manual/html_node/Regexp-Operators.html#Regexp-Operators )

0
28.01.2020, 04:50
awk '/^[0-9]{2}[.][0-9]{2}[.][0-9]{4}/ {DATES[$1]++} 
     END{ for(d in DATES) {print d} }'

В отличие от "камень, бумага, ножницы": awk всегда побеждает sed. :-)

Редактирование: вот он в действии:

$ cut -b-60 t
15.04.2016 13:13:30,228 INFO    [wComService] [mukumukuko@sy
15.05.2016 13:14:10,886 INFO    [wComService] Call 5303 from
15.06.2016 13:14:20,967 INFO    [AddressTranslatorService][m
15.07.2016 13:14:20,992 INFO    [wComService] [mukumukuko@sy
15.04.2016 13:15:18,760 INFO    [OSMCService] SessionManager
this file contains the activity log of 1 week, so in the fil

The file can have also these outputs from Java exception:

    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanE
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl
    at org.apache.xerces.parsers.XML11Configuration.parse(Un
    at org.apache.xerces.parsers.XML11Configuration.parse(Un

$ awk '/^[0-9]{2}[.][0-9]{2}[.][0-9]{4}/ {DATES[$1]++} 
     END{ for(d in DATES) { print d } }' t
15.07.2016
15.06.2016
15.04.2016
15.05.2016

Это GNU awk. Если ваша версия awk не выводит результат, это, вероятно, потому, что ее реализация регулярных выражений отличается и не сопоставляет строки. Например, она может не поддерживать скобки как спецификатор повторения. Ценой потери специфичности можно упростить regex до /^[0-9]/, что определенно сработает. Это позволит отловить даты и устранить сообщения журнала, но может зацепить и не даты.

Некоторые эксперименты и время, проведенное с вашим дружественным руководством по awk, могут оказаться плодотворными. ;-)

.
0
28.01.2020, 04:50

Теги

Похожие вопросы