解析日志文件中的行并提取兴趣点的有效(性能和可读性)是什么?
例如:
*** Time: 2/1/2019 13:51:00
17.965 Pump 10 hose FF price level 1 limit 0.0000 authorise pending (Type 00)
17.965 Pump 10 State change LOCKED_PSTATE to CALLING_PSTATE [31]
38.791 Pump 10 delivery complete, Hose 1, price 72.9500, level 1, value 100.0000, volume 1.3700, v-total 8650924.3700, m-total 21885705.8800, T13:51:38
我需要提取的东西是10(对于泵10),价格水平。限制 _PSTATE更改交货完成行等中的值。
目前,我正在使用正则表达式捕获每个表达式并使用捕获组。但是感觉效率很低,而且有很多重复。
例如,我有一堆:
reStateChange := regexp.MustCompile(`^(?P<offset>.*) Pump (?P<pump>\d{2}) State change (?P<oldstate>\w+_PSTATE) to (?P<newstate>\w+)_PSTATE`)
然后在while循环中
if match := reStateChange.FindStringSubmatch(text); len(match) > 0 {
matched = true
for i, name := range match {
result[reStateChange.SubexpNames()[i]] = name
}
} else if match := otherReMatch.FindStringSubmatch(text); len(match) > 0 {
matched = true
for i, name := range match {
result[reStateChange.SubexpNames()[i]] = name
}
} else if strings.Contains(text, "*** Time:") {
}
感觉有更好的方法可以做到这一点。我会为了获得可读性而牺牲一些性能。日志文件实际上最多只有10MB。通常较小。
我正在寻求有关如何在golang中使其变得更好的一些建议。
答案 0 :(得分:0)
如果您的所有日志行都与您发布的示例相似,则它们似乎结构合理,因此正则表达式可能有点过大且难以一概而论。
另一个选择是,您可以使用strings.Fields甚至是strings.FieldFunc将这些行中的每行转换为一片字符串([]string
),以便您可以同时删除两个空格和逗号。
然后您可以设计一个界面,例如:
type LogLineProcessor interface {
CanParse(line []string)
GetResultFrom(line []string) LogLineResult
}
LogLineResult
是包含所提取信息的结构。
然后,您可以使用实现LogLineProcessor
的方法定义多个结构(每个实现都会查看该[]string
上的特定位置,以了解它是否可以处理,例如查找希望找到它们的位置上有“软管”,“ FF”和“价格”字样。
GetResultFrom
实现也将从[]string
中的特定位置提取每个数据点(如果它已经确定它是可以处理的行之一,则可以依赖那里的信息)。
您可以创建一个var processors []LogLineProcessor
,将所有处理器放入其中,然后仅迭代该数组:
line := strings.Fields(text)
for _, processor := range processors {
if processor.CanParse(line) {
result := processor.GetResultFrom(line)
// do whatever needed with the result
}
}