【问题标题】:Parse a log file to fetch some values in a line解析日志文件以获取一行中的一些值
【发布时间】:2021-06-19 05:52:59
【问题描述】:

我正在读取一个日志文件,在该文件中我试图从包含子字符串“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 库中存在的任何其他功能的任何建议可以帮助我完成此任务,请告诉我。

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

【问题讨论】:

    标签: regex tcl


    【解决方案1】:

    为了安全起见,我会修改正则表达式以查找单词之间的空格 ([[: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

    【讨论】:

    • 我尝试了表达式,但似乎仍然不匹配。
    • 啊,似乎 Tcl 正则表达式的风格非常有限。我需要修改答案 - 您使用的是哪个版本的 Tcl?
    • 现在基于this cheatsheet修改了Tcl 8.1+的正则表达式。
    【解决方案2】:

    首先,将一个人的名字分解成其组成部分是非常困难的。例如,有些人有一个多字姓氏。 (是的,我知道具体的个例子。)其他人将零件按不同的顺序排列。能不分名字吗?

    解析该子字符串的其他部分更容易,因为我们可以假设 agentrole 不会有空格。这个 RE 的诀窍是 \w+ 匹配“单词”字符序列,@987654324 @ 匹配空格字符序列(比单个空格更健壮),.*? 匹配任何内容,但尽可能少。

    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
    

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

    【讨论】:

    • 理想情况下,您应该记录用户 ID 而不是名称。
    • 感谢您的回答。我需要名称,因为我们没有记录用户名。另外我刚刚意识到,在我们的日志中,有些情况下人们没有任何角色。因此,它们被分配了一个连字符 (-) 值。如下所示,2021 年 6 月 19 日 LOGGER:INFO 编辑者:Person Jack Rudoplh - 再见。因此,情况各不相同,现在使用正则表达式来满足这些需求变得更加困难。
    • 解决方法不错。但我检查了我的日志在编辑之前有一个额外的空格字符,冒号 (:) 和 by 之间有空格。 编辑: 人 James Cooper 管理员再见。我该如何合并这个案例
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多