解析日志文件以获取一行中的一些值

Parse a log file to fetch some values in a line

我正在读取一个日志文件,我试图从其中包含子字符串“edited by:”并以“bye”结尾的行中获取一些值。

这就是日志文件的设计方式。

Error nothing reported
19-06-2021 LOGGER:INFO edited by : James Cooper Person  Administrator bye.  //Line 2
No data match.
19-06-2021 LOGGER:INFO edited by : Harry Rhodes Person External bye.        //Line 4
.......

所以我正在尝试获取:

James Cooper Person Administrator   //from line 2
Harry Rhodes Person External        //from line 4

并将它们分配给我的 tcl 程序中的变量。

我假设获取的行在列表名称 line2 中。 喜欢

set splitList[$line2 ' ']
set agent [lindex $splitList 0]
set firstName [lindex $splitList 1]
set lastName [lindex $splitList 2]
set role [lindex $splitList 3]

我知道将日志文件中提取或提取的行放在列表中并不是一个好主意,因为它们是非结构化输入。如果 Tcl 列表函数不符合正确的 Tcl 列表格式,则使用 Tcl 列表函数可能会导致奇怪的事情。

我是 tcl 的新手。并且不太了解在 tcl 中使用正则表达式。

所以我尝试使用正则表达式从匹配的行中提取值。假设 line2 是一个变量,保存从日志文件中提取的匹配的 line2,

regexp -- {edited by:(.*) bye.$} $line2 match agent

我能够得到如下所示的预期输出。

Person Harry Rhodes External

但是,在这个提取的字符串上,我不知道如何进一步钻取来为我的变量赋值。关于这种方法的任何建议或 tcl 库中存在的任何其他功能可以帮助我完成此任务,请告诉我。

通过编辑日志格式更新了问题。日志文件的格式不正确。

首先,将一个人的名字分解成它的组成部分是非常困难的。例如,有些人的姓氏有多个单词。 (是的,我知道 具体 这方面的例子。)其他人以不同的顺序排列这些部分。能不能不拆名字?

解析该子字符串的其他部分更容易,因为我们可以假设 agentrole 不会包含 space。这个 RE 的技巧是 \w+ 匹配一个“单词”字符序列,\s+ 匹配一个 space 字符序列(比单个 space 更稳健),.*? 匹配任何东西,但同样少尽可能的。

regexp {^\s*(\w+)\s+(.*?)\s+(\w+)\s*$} $substring -> agent name role

好的,这对子字符串来说很好,但是整行呢?这实际上只是调整锚点的问题。 (\y 匹配单词边界。)

regexp {\yedited by:\s*(\w+)\s+(.*?)\s+(\w+)\s+bye\y} $line -> agent name role

在正则表达式搜索中一次输入多于一行通常不是一个好主意,除非您需要这样做。幸运的是,您的记录是用换行符分隔的,所以这不是问题。

为了安全起见,我会修改正则表达式以查找单词之间的空格 ([[:space:]]),使用 * (= "any amount") 和 + (= "至少一个") 并将每个变量存储在捕获组中(用括号括起来 ()):

edited[[:space:]]+by[[:space:]]*:[[:space:]]*([^[:space:]]*)[[:space:]]+([^[:space:]]*)[[:space:]]+([^[:space:]]*)[[:space:]]+([^[:space:]]*)[[:space:]]+bye.$

请注意 [^[:space:]] 匹配除空格以外的任何字符。

Regex101 演示:https://regex101.com/r/78l4HJ/1