dongshao2967
dongshao2967
2017-06-13 08:50
浏览 183
已采纳

在golang中捕获ping命令的结果

I have result of ping command in two ways->

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

these are results of ping command in two different platforms. Now From this I want value of avg/stddev in both the cases. I have written a regex-

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)
}

Now this pattern is working fine for 2nd result of ping (giving me 0.034 and 0.01 as result). But for result 1, it is not able to find the pattern (i.e. to give 0.078 and 0.007). How can I change the regex to work for both?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • doulu1325
    doulu1325 2017-06-13 10:32
    已采纳

    You need to be more precise when defining the regex. .* is too greedy and matches across commas and other stuff.

    I suggest using

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

    See the 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
    ", latency, jitter)
    
            }
    }
    

    Result:

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

    Pattern details:

    • (round-trip|rtt) - round-trip or rtt substrings
    • \s+ - 1+ whitespaces
    • \S+ - 1+ non-whitespace symbols
    • \s*=\s* - a = enclosed with 0+ whitespaces
    • ([0-9.]+) - Group 1: the first number
    • / - a /
    • ([0-9.]+) - Group 2: the second number
    • / - a /
    • ([0-9.]+) - Group 3: the third number
    • / - a /
    • ([0-9.]+) - Group 4: the fourth number
    • \s* - 0+ whitespaces
    • ms - a substring ms
    点赞 评论
  • doumibi6899
    doumibi6899 2017-06-13 13:19

    Personally, I would simplify this as much as possible, especially since you aren't trying to pull out all the data, just a couple parts - which are conveniently in the same format in both versions! Essentially, in that string, you only care about 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
    ", parts[1], parts[3])
    

    Example on playground.

    点赞 评论

相关推荐