解析日志文件以获取一行中的一些值
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 库中存在的任何其他功能可以帮助我完成此任务,请告诉我。
通过编辑日志格式更新了问题。日志文件的格式不正确。
首先,将一个人的名字分解成它的组成部分是非常困难的。例如,有些人的姓氏有多个单词。 (是的,我知道 具体 这方面的例子。)其他人以不同的顺序排列这些部分。能不能不拆名字?
解析该子字符串的其他部分更容易,因为我们可以假设 agent
和 role
不会包含 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
我正在读取一个日志文件,我试图从其中包含子字符串“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 库中存在的任何其他功能可以帮助我完成此任务,请告诉我。
通过编辑日志格式更新了问题。日志文件的格式不正确。
首先,将一个人的名字分解成它的组成部分是非常困难的。例如,有些人的姓氏有多个单词。 (是的,我知道 具体 这方面的例子。)其他人以不同的顺序排列这些部分。能不能不拆名字?
解析该子字符串的其他部分更容易,因为我们可以假设 agent
和 role
不会包含 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