capture result of ping command in golang

huangapple go评论73阅读模式
英文:

capture result of ping command in golang

问题

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

1->已发送 5 个数据包,已接收 5 个数据包,丢失 0.0%
往返的最小值/平均值/最大值/标准差 = 0.067/0.078/0.087/0.007 ms

2->已发送 5 个数据包,已接收 5 个数据包,丢失 0%
时间 801ms
往返时间的最小值/平均值/最大值/标准差 = 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作为结果)。但是对于第一个结果,它无法找到匹配的模式(即无法给出0.078和0.007)。
我该如何修改正则表达式以适应两种情况?

英文:

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?

答案1

得分: 2

你需要在定义正则表达式时更加精确。.*太贪婪了,会匹配逗号和其他内容。

我建议使用以下正则表达式:

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

可以在正则表达式演示中查看示例。

Go语言示例代码:

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个或多个空格字符
  • ms - 匹配子字符串 ms
英文:

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\n", 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

答案2

得分: 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])

在 playground 上的示例

英文:

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\n", parts[1], parts[3])

Example on playground.

huangapple
  • 本文由 发表于 2017年6月13日 16:50:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/44516601.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定