从日志文件中提取日期并创建具有唯一日期的文件

从日志文件中提取日期并创建具有唯一日期的文件

我想从文件中提取格式为日期的日期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

但我在“datesF1”中得到了所需的日期,但带有这些 Java 异常消息

所以我想要的是生成一个仅显示唯一日期而不重复它们的文件,例如“datesF1”必须是:

15.04.2016
16.04.2016
17.04.2016
18.04.2016

您知道这是否可行或者使用 grep 命令是否更好?

答案1

sed 命令不起作用的原因是它假设每行都有一个日期,如果某些行来自多行错误消息,则情况并非如此。当没有任何内容与替换模式匹配时,sed 不会进行替换,您看到的调用堆栈列表仍保留在输出中。

要仅从开头包含日期的行中获取日期,您有多种选择:

格列普:

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

-o 告诉 grep 只打印匹配的部分,而不是整行,-E 启用“扩展”正则表达式

awk:

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

awk 命令的第一部分是正则表达式匹配,其余部分是如何处理匹配行,这里我们打印该行的第一个单词。

珀尔:

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

-l:在每个上打印一个换行符print,-n:为每一行输入运行命令(如 awk),-e:只是告诉程序是在命令行上给出的,而不是在文件中给出的。

在所有情况下,每个匹配的输入行都会得到一行输出,即重复日期。通过管道传递结果| sort | uniq可能是删除重复项的最简单的习惯用法。

请注意,我很懒,没有使用^[0-9.]+更长、更精确的模式。这与我喜欢使用 perl 而不是 sed、awk 和朋友的原因有关:Perl 正则表达式总是相同的,无论你在做什么。另外,在 Perl 中,无需记住默认支持哪些修饰符,以及哪些需要设置 -E 或其他内容。然后是版本之间的差异:显然我的 Debian 系统默认使用 mawk 而不是 GNU awk,而且它似乎不支持 {N} 修饰符,因此更精确的模式不起作用。哎呀。

GNU awk 手册:“间隔表达式在 awk 中传统上不可用。它们是作为 POSIX 标准的一部分添加的,以使 awk 和 egrep 彼此一致。” (参考。https://www.gnu.org/software/gawk/manual/html_node/Regexp-Operators.html#Regexp-Operators

答案2

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 版本不产生输出,可能是因为它的正则表达式实现不同,并且不匹配任何行。例如,它可能不支持大括号作为重复说明符。以失去特异性为代价,您可以将正则表达式简化为/^[0-9]/,这肯定会起作用。这将捕获日期并消除日志消息,但也可能会捕获一些非日期。

一些实验和时间与你友好的 awk 手册可能会证明是富有成效的。 ;-)

相关内容