Goland逐行读取命令的输出结果

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

Goland reading liner per line output of a command

问题

我想逐行读取输出命令。为此,我使用了StdoutPipe方法和bufio库:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os/exec"
	"bufio"
)


func main() {
	cmd := exec.Command("printf", "{\"Name\": \"Bob\", \"Age\": 1}\n%.0s", "{1..5}")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	scanner := bufio.NewScanner(stdout)
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	var person struct {
		Name string
		Age  int
	}
	for scanner.Scan() {
		if err := json.Unmarshal([]byte(scanner.Text()), &person); err != nil {
			log.Fatal(err)
		} else {
			fmt.Printf("%s is %d years old\n", person.Name, person.Age)
		}
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
}

我应该得到5行输出:

$ printf "{\"Name\": \"Bob\", \"Age\": 1}\n%.0s" {1..5}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}

问题在于我只得到了第一行。我对Go不太熟悉,我猜测StdoutPipe的使用方法不正确。

英文:

I would like to read an output command line per line. For this I use the StdoutPipe method and the bufio library:

package main

import (
        "encoding/json"
        "fmt"
        "log"
        "os/exec"
        "bufio"
)


func main() {
        cmd := exec.Command("printf", "{\"Name\": \"Bob\", \"Age\": 1}\n%.0s", "{1..5}")
        stdout, err := cmd.StdoutPipe()
        if err != nil {
                log.Fatal(err)
        }
        scanner := bufio.NewScanner(stdout)
        if err := cmd.Start(); err != nil {
                log.Fatal(err)
        }
        var person struct {
                Name string
                Age  int
        }
        for scanner.Scan() {
                if err := json.Unmarshal([]byte(scanner.Text()), &person); err != nil {
                        log.Fatal(err)
                } else {
                        fmt.Printf("%s is %d years old\n", person.Name, person.Age)
                }
        }
        if err := cmd.Wait(); err != nil {
                log.Fatal(err)
        }
}

I should obtain 5 lines:

$ printf "{\"Name\": \"Bob\", \"Age\": 1}\n%.0s" {1..5}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}

The point is that I only get the first line. I am quite new on Goand I guess the usage of the StdoutPipe is incorrect.

答案1

得分: 1

{1..5}在shell中被展开为1 2 3 4 5,所以你必须自己完成这个操作:

cmd := exec.Command("printf", `{"Name": "Bob", "Age": %s}\n`, `1`, `2`) // 等等。

另外请注意使用原始字符串,它比不断转义所有内容更方便。另外,与此相关的是,你应该真正使用scanner.Bytes()而不是[]byte(scanner.Text())

英文:

{1..5} is expanded to 1 2 3 4 5 by the shell, so you must do it yourself:

cmd := exec.Command("printf", `{"Name": "Bob", "Age": %s}\n`, `1`, `2`) // etc.

Also note the use of raw strings, its much more convenient than constantly escaping everything. And on a related note, instead of []byte(scanner.Text()) you should really use scanner.Bytes().

huangapple
  • 本文由 发表于 2016年2月5日 18:16:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/35221537.html
匿名

发表评论

匿名网友

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

确定