在golang中捕获ping命令的结果

时间:2017-06-13 08:50:35

标签: regex go

我有ping命令的结果有两种方式 - >

1->5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.067/0.078/0.087/0.007 ms

2->5 packets transmitted, 5 received, 0% packet loss, time 801ms
rtt min/avg/max/stddev = 0.019/0.034/0.044/0.010 ms, ipg/ewma 200.318/0.038 ms

这些是两个不同平台中ping命令的结果。 现在,我希望在这两种情况下都能获得avg / stddev的值。 我写了一个正则表达式 -

var latencyPattern = regexp.MustCompile("(round-trip|rtt) .* = (.*)/(.*)/(.*)/(.*) *ms,")
if matches := latencyPattern.FindStringSubmatch(strOutput); len(matches) >= 5{
    latency, _ = strconv.ParseFloat(strings.TrimSpace(matches[3]), 64)
    jitter, _ = strconv.ParseFloat(strings.TrimSpace(matches[5]), 64)
}

现在这个模式对于ping的第二个结果工作正常(给我0.034和0.01作为结果)。但是对于结果1,它无法找到模式(即给出0.078和0.007)。 如何更改正则表达式以适用于两者?

2 个答案:

答案 0 :(得分:2)

定义正则表达式时需要更精确。 .*过于贪婪,并且可以使用逗号和其他内容进行匹配。

我建议使用

var latencyPattern = regexp.MustCompile(`(round-trip|rtt)\s+\S+\s*=\s*([0-9.]+)/([0-9.]+)/([0-9.]+)/([0-9.]+)\s*ms`)

请参阅regex demo

Go lang demo

package main

import (
    "fmt"
    "regexp"
    "strings"
    "strconv"
)

func main() {
    strOutput := `1->5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.067/0.078/0.087/0.007 ms 
        2->5 packets transmitted, 5 received, 0% packet loss, time 801ms
rtt min/avg/max/stddev = 0.019/0.034/0.044/0.010 ms, ipg/ewma 200.318/0.038 ms`
    latencyPattern := regexp.MustCompile(`(round-trip|rtt)\s+\S+\s*=\s*([0-9.]+)/([0-9.]+)/([0-9.]+)/([0-9.]+)\s*ms`)
    matches := latencyPattern.FindAllStringSubmatch(strOutput, -1)
    for _, item := range matches {
        latency, _ := strconv.ParseFloat(strings.TrimSpace(item[3]), 64)
            jitter, _ := strconv.ParseFloat(strings.TrimSpace(item[5]), 64)
            fmt.Printf("AVG = %.3f, STDDEV = %.3f\n", latency, jitter)

        }
}

结果:

AVG = 0.078, STDDEV = 0.007
AVG = 0.034, STDDEV = 0.010

模式详情

  • (round-trip|rtt) - round-triprtt子字符串
  • \s+ - 1+空格
  • \S+ - 1个非空白符号
  • \s*=\s* - 包含0 +空格的=
  • ([0-9.]+) - 第1组:第一个数字
  • / - /
  • ([0-9.]+) - 第2组:第二个数字
  • / - /
  • ([0-9.]+) - 第3组:第三个数字
  • / - /
  • ([0-9.]+) - 第4组:第四个数字
  • \s* - 0+ whitespaces
  • ms - 子字符串ms

答案 1 :(得分:0)

就个人而言,我会尽可能地简化这一点,特别是因为你不是想要提取所有数据,只是几个部分 - 在两个版本中都方便地使用相同的格式!基本上,在该字符串中,您只关心min/avg/max/stddev = 0.019/0.034/0.044/0.010

re := regexp.MustCompile("min/avg/max/stddev = ([0-9./]+)")
sub := re.FindStringSubmatch(input)
parts := strings.Split(sub[1], "/")
fmt.Printf("Avg: %s, StdDev: %s\n", parts[1], parts[3])

Example on playground