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?
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
", 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+ whitespacesms
- a substring ms
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])