尝试使用Golang解析命令行上的stdout。

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

Trying to parse a stdout on command line with Golang

问题

我正在练习使用Go语言将参数传递给命令行,并能够解析传递出来的结果信息。例如,我有一段代码用于执行命令,并显示通过cmd输入命令时将要显示的内容。

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

func main() {
    cmd := exec.Command("ping", "8.8.8.8")
	cmdOutput := &bytes.Buffer{}
	cmd.Stdout = cmdOutput
	printCommand(cmd)
	err := cmd.Run()
	printError(err)
	printOutput(cmdOutput.Bytes())
}

func printCommand(cmd *exec.Cmd) {
	fmt.Printf("==> Executing: %s\n", strings.Join(cmd.Args, " "))
}

func printError(err error) {
	if err != nil {
		os.Stderr.WriteString(fmt.Sprintf("==> Error: %s\n", err.Error()))
	}
}

func printOutput(outs []byte) {
	if len(outs) > 0 {
		fmt.Printf("==> Output: %s\n", string(outs))
	}
}

考虑到输出将会是:

==> Executing: ping 8.8.8.8
==> Output:
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=13ms TTL=56
Reply from 8.8.8.8: bytes=32 time=13ms TTL=56
Reply from 8.8.8.8: bytes=32 time=14ms TTL=56
Reply from 8.8.8.8: bytes=32 time=11ms TTL=56

Ping statistics for 8.8.8.8:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% lo
Approximate round trip times in milli-seconds:
    Minimum = 11ms, Maximum = 14ms, Average = 12ms

我的问题是:如果我想解析平均响应时间,以便将其赋值给一个变量,以便在需要时显示它,我该如何解析它?

英文:

I'm practicing to use GoLang to pass arguements to the command line, and being able to parse information from the results that are passed out. For example, I have code that is designed to execute a command, and display what will display anyway if the command was entered through cmd anyway.

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

func main() {
    cmd = exec.Command("ping", "8.8.8.8")
	cmdOutput = &bytes.Buffer{}
	cmd.Stdout = cmdOutput
	printCommand(cmd)
	err = cmd.Run()
	printError(err)
	printOutput(cmdOutput.Bytes())
}

func printCommand(cmd *exec.Cmd) {
	fmt.Printf("==> Executing: %s\n", strings.Join(cmd.Args, " "))
}

func printError(err error) {
	if err != nil {
		os.Stderr.WriteString(fmt.Sprintf("==> Error: %s\n", err.Error()))
	}
}

func printOutput(outs []byte) {
	if len(outs) > 0 {
		fmt.Printf("==> Output: %s\n", string(outs))
	}
}

Considering the output would be:

==> Executing: ping 8.8.8.8
==> Output:
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=13ms TTL=56
Reply from 8.8.8.8: bytes=32 time=13ms TTL=56
Reply from 8.8.8.8: bytes=32 time=14ms TTL=56
Reply from 8.8.8.8: bytes=32 time=11ms TTL=56

Ping statistics for 8.8.8.8:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% lo
Approximate round trip times in milli-seconds:
    Minimum = 11ms, Maximum = 14ms, Average = 12ms

My question is: If I wanted to parse the Average response time, so I can assign that to a variable so I can display that when I want to, how can I parse that?

答案1

得分: 6

你可以使用regexp来实现。例如,像这样的代码:

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"time"
)

type Ping struct {
	average time.Duration
}

func main() {
	cmd := exec.Command("ping", "8.8.8.8")
	// Linux 版本
	//cmd := exec.Command("ping", "-c 4", "8.8.8.8")
	cmdOutput := &bytes.Buffer{}
	cmd.Stdout = cmdOutput
	printCommand(cmd)
	err := cmd.Run()
	printError(err)
	output := cmdOutput.Bytes()
	printOutput(output)
	ping := Ping{}
	parseOutput(output, &ping)

	fmt.Println(ping)
}

func printCommand(cmd *exec.Cmd) {
	fmt.Printf("==> 执行命令: %s\n", strings.Join(cmd.Args, " "))
}

func printError(err error) {
	if err != nil {
		os.Stderr.WriteString(fmt.Sprintf("==> 错误: %s\n", err.Error()))
	}
}

func printOutput(outs []byte) {
	if len(outs) > 0 {
		fmt.Printf("==> 输出: %s\n", string(outs))
	}
}

func parseOutput(outs []byte, ping *Ping) {
	var average = regexp.MustCompile(`Average = (\d+ms)`)
	result := average.FindStringSubmatch(string(outs))

	if len(result) > 0 {
		ping.average, _ = time.ParseDuration(result[1])
	}
	// Linux 版本
	/*var average = regexp.MustCompile(`min/avg/max/mdev = (0.\d+)/(0.\d+)/(0.\d+)/(0.\d+) ms`)
	result := average.FindAllStringSubmatch(string(outs), -1)

	if len(result) > 0 {
		ping.average, _ = time.ParseDuration(result[0][2] + "ms")
	}*/
}

这段代码使用了regexp包来解析命令行输出中的平均时间。你可以根据需要进行修改和使用。

英文:

You can use regexp. For instance something like:

package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"time"
)
type Ping struct {
average time.Duration
}
func main() {
cmd := exec.Command("ping", "8.8.8.8")
// Linux version
//cmd := exec.Command("ping", "-c 4", "8.8.8.8")
cmdOutput := &bytes.Buffer{}
cmd.Stdout = cmdOutput
printCommand(cmd)
err := cmd.Run()
printError(err)
output := cmdOutput.Bytes()
printOutput(output)
ping := Ping{}
parseOutput(output, &ping)
fmt.Println(ping)
}
func printCommand(cmd *exec.Cmd) {
fmt.Printf("==> Executing: %s\n", strings.Join(cmd.Args, " "))
}
func printError(err error) {
if err != nil {
os.Stderr.WriteString(fmt.Sprintf("==> Error: %s\n", err.Error()))
}
}
func printOutput(outs []byte) {
if len(outs) > 0 {
fmt.Printf("==> Output: %s\n", string(outs))
}
}
func parseOutput(outs []byte, ping *Ping) {
var average = regexp.MustCompile(`Average = (\d+ms)`)
result := average.FindStringSubmatch(string(outs))
if len(result) > 0 {
ping.average, _ = time.ParseDuration(result[1])
}
// Linux version
/*var average = regexp.MustCompile(`min\/avg\/max\/mdev = (0\.\d+)\/(0\.\d+)\/(0\.\d+)\/(0\.\d+) ms`)
result := average.FindAllStringSubmatch(string(outs), -1)
if len(result) > 0 {
ping.average, _ = time.ParseDuration(result[0][2] + "ms")
}*/
}

huangapple
  • 本文由 发表于 2017年2月14日 05:35:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/42213996.html
匿名

发表评论

匿名网友

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

确定