英文:
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-trip
或rtt
子字符串\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.
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
orrtt
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+ whitespacesms
- a substringms
答案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])
英文:
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])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论