为了账号安全,请及时绑定邮箱和手机立即绑定

如何调用外部程序并处理其输出?

如何调用外部程序并处理其输出?

Go
千万里不及你 2022-06-13 15:34:31
我正在尝试调用外部命令(例如,seq 10)并获取其输出,处理输出然后打印出处理后的结果。但是下面的代码不起作用。你能告诉我如何让它工作吗?// vim: set noexpandtab tabstop=2:package mainimport (    "bufio"    "io"    "os"    "log"    "os/exec")func main() {    cmd := exec.Command("seq", "10")    stdin := bufio.NewReader(cmd.Stdout)    err := cmd.Run()    if err != nil {        log.Fatalf("cmd.Run() failed with %s\n", err)    }    for {        line, err := stdin.ReadBytes('\n')        if err == io.EOF {            if len(line) == 0 { break }        } else {            if err != nil { log.Fatal(err) }            line = line[:(len(line)-1)]        }        os.Stdout.Write(line)        os.Stdout.Write([]byte{'\n'})    }}$ $ go run main.go # command-line-arguments./main.go:15:30: cannot use cmd.Stdout (type io.Writer) as type io.Reader in argument to bufio.NewReader:    io.Writer does not implement io.Reader (missing Read method)编辑:我也试过这个。但它也有错误。谁能给我看一个可行的例子。// vim: set noexpandtab tabstop=2:package mainimport (    "bufio"    "io"    "os"    "log"    "os/exec")func main() {    cmd := exec.Command("seq", "10")    stdout, err := cmd.StdoutPipe()    if err != nil { log.Fatal(err) }    stdin := bufio.NewReader(stdout)    err = cmd.Run()    if err != nil {        log.Fatalf("cmd.Run() failed with %s\n", err)    }    for {        line, err := stdin.ReadBytes('\n')        if err == io.EOF {            if len(line) == 0 { break }        } else {            if err != nil { log.Fatal(err) }            line = line[:(len(line)-1)]        }        os.Stdout.Write(line)        os.Stdout.Write([]byte{'\n'})    }}
查看完整描述

2 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

另一种方法(也是一种更简洁的方法)是自动使用bufio.Scanner哪个句柄\n(或任何其他分隔符)。另一个优点是这种方法没有种族问题(去过那里,做过):


package main


import (

    "bufio"

    "fmt"

    "log"

    "os/exec"

)


func main() {

    cmd := exec.Command("seq", "10")

    stdout, err := cmd.StdoutPipe()

    if err != nil {

        log.Fatal(err)

    }

    err = cmd.Start()

    if err != nil {

        log.Fatalf("cmd.Start() failed with %s\n", err)

    }


    stdin := bufio.NewScanner(stdout)

    for stdin.Scan() {

        fmt.Println(stdin.Text())

    }

    cmd.Wait()

}

stdin.Scan()返回 false on EOF,一旦进程退出就会给出。cmd.Wait()将关闭StdoutPipe,您可以阅读err.(exec.ExitError).ExitCode()以获取退出代码(如果退出非零)。


查看完整回答
反对 回复 2022-06-13
?
jeck猫

TA贡献1909条经验 获得超7个赞

您需要使用管道将标准输出到阅读器.StdoutPipe(),还需要使用exec.Command(..).Start()增量读取(.Run()等待进程退出)。这是工作代码:


// vim: set noexpandtab tabstop=2:


package main


import (

    "bufio"

    "fmt"

    "io"

    "log"

    "os"

    "os/exec"

)


func main() {

    cmd := exec.Command("seq", "10")

    cmdStdOut, err := cmd.StdoutPipe()

    cmdStdErr, err := cmd.StderrPipe()

    defer cmdStdOut.Close()

    if err != nil {

        log.Fatalf("command failed with %s\n", err)

    }

    stdoutReader := bufio.NewReader(cmdStdOut)

    stderrReader := bufio.NewReader(cmdStdErr)

    err = cmd.Start()

    if err != nil {

        log.Fatalf("cmd.Run() failed with %s\n", err)

    }

    // Read stdout

    for {

        line, err := stdoutReader.ReadBytes('\n')

        if err == io.EOF {

            if len(line) == 0 {

                break

            }

        } else {

            if err != nil {

                log.Fatal(err)

            }

            line = line[:(len(line) - 1)]

        }

        os.Stdout.Write(line)

        os.Stdout.Write([]byte{'\n'})

    }

    // Read stderr

    for {

        line, err := stderrReader.ReadBytes('\n')

        if err == io.EOF {

            if len(line) == 0 {

                break

            }

        } else {

            if err != nil {

                log.Fatal(err)

            }

            line = line[:(len(line) - 1)]

        }

        os.Stderr.Write(line)

        os.Stderr.Write([]byte{'\n'})

    }

    cmd.Wait()

    fmt.Println(cmd.ProcessState.ExitCode())

}


查看完整回答
反对 回复 2022-06-13
  • 2 回答
  • 0 关注
  • 177 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号